为什么我的函数不能访问它所在的 class 的私有变量 INSIDE?
Why can't my function access a private variable INSIDE of the class it's in?
编辑:我对 null 错误的含义并不感到困惑,我知道我的列表是 null。我只是不确定为什么在这种情况下它会为空,或者为什么将我的列表设置为 public 突然解决了这个问题。
所以,我正在尝试制作一个函数,如果它满足条件,就会将对象添加到列表中。该函数接受它正在检查的标签,如果可能的话,它会把它添加到特定的列表中。我这样做的原因是因为我有两个列表,我宁愿两个列表只需要一个函数。
这一切都很好,但我遇到了一个问题,它不......除非列表设置为 public,否则它似乎真的有效?如果可以的话,我宁愿不这样做。
我不明白为什么,因为它可以很好地处理私有 gameObject 引用,并且在同一个位置声明,并且函数在同一个 class 内,但试图在列表是私有的时候调用这个函数给我一个空对象引用错误,在这种情况下我已经缩小到列表为空,而不是对象?
这没什么大不了的,因为我可以改变一些事情来避免出现列表 public,但我真的很困惑为什么会这样?我试过通过 ref 显式传递,但出现了同样的问题。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ClickHandler : MonoBehaviour
{
GameObject clickedMob = null;
List<GameObject> selectedMinions;
List<GameObject> selectedHostiles;
void Update ( )
{
if ( Input.GetButtonDown("Click"))
{
switch (clickState)
{
case NextClickAction.Nothing:
{ }
break;
case NextClickAction.TargetFriendly:
{
hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if ( hit )
{
if ( hit.transform != null )
{
clickedMob = hit.transform.gameObject;
CheckObject("Minion", selectedMinions);
}
}
}
break;
case NextClickAction.TargetHostile:
{
hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if ( hit )
{
if ( hit.transform != null )
{
clickedMob = hit.transform.gameObject;
CheckObject("Hostile", selectedHostiles);
}
}
}
break;
default:
{
Debug.Log("why do you have an enum this big");
DeactivateClick();
Debug.LogError("Enum set outside of index. Returned to 0.");
break;
}
}
}
} // end of update
private void CheckObject ( string tag , List<GameObject> mobList)
{
if ( clickedMob.CompareTag(tag) )
{
if ( clickedMob.GetComponent<Animator>() != null )
{
ClickedMobAnimator = clickedMob.GetComponent<Animator>();
switch (ClickedMobAnimator.GetBool("Selected"))
{
case true:
ClickedMobAnimator.SetBool("Selected", false); // Setting the object to have a little box around it when it's selected.
mobList.Remove(clickedMob);
Debug.Log(mobList.Count + " " + clickedMob);
break;
case false:
ClickedMobAnimator.SetBool("Selected", true);
mobList.Add(clickedMob);
Debug.Log(mobList.Count + " " + clickedMob);
break;
}
}
}
}
此代码的输出:
NullReferenceException: Object reference not set to an instance of an object
ClickHandler.CheckObject (System.String tag, System.Collections.Generic.List'[T] mobList) (at Assets/Scripts/ClickHandler.cs:119)
而且我知道在这种情况下该对象不是 null,因为我有一个调试日志打印该对象。就在那里。
由于您的列表是非公开的并且也是非序列化的字段,您不能从检查器分配它们以自动创建新的列表实例,因此在您的 ClickHandler 脚本中添加 Awake 方法,您可以在其中将它们实例化为新的列表对象。
void Awake() {
selectedMinions = new List<GameObject>();
selectedHostiles = new List<GameObject>();
}
或者您可以在申报时做同样的事情
List<GameObject> selectedMinions = new List<GameObject>();
List<GameObject> selectedHostiles = new List<GameObject>();
编辑:我对 null 错误的含义并不感到困惑,我知道我的列表是 null。我只是不确定为什么在这种情况下它会为空,或者为什么将我的列表设置为 public 突然解决了这个问题。
所以,我正在尝试制作一个函数,如果它满足条件,就会将对象添加到列表中。该函数接受它正在检查的标签,如果可能的话,它会把它添加到特定的列表中。我这样做的原因是因为我有两个列表,我宁愿两个列表只需要一个函数。
这一切都很好,但我遇到了一个问题,它不......除非列表设置为 public,否则它似乎真的有效?如果可以的话,我宁愿不这样做。 我不明白为什么,因为它可以很好地处理私有 gameObject 引用,并且在同一个位置声明,并且函数在同一个 class 内,但试图在列表是私有的时候调用这个函数给我一个空对象引用错误,在这种情况下我已经缩小到列表为空,而不是对象?
这没什么大不了的,因为我可以改变一些事情来避免出现列表 public,但我真的很困惑为什么会这样?我试过通过 ref 显式传递,但出现了同样的问题。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ClickHandler : MonoBehaviour
{
GameObject clickedMob = null;
List<GameObject> selectedMinions;
List<GameObject> selectedHostiles;
void Update ( )
{
if ( Input.GetButtonDown("Click"))
{
switch (clickState)
{
case NextClickAction.Nothing:
{ }
break;
case NextClickAction.TargetFriendly:
{
hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if ( hit )
{
if ( hit.transform != null )
{
clickedMob = hit.transform.gameObject;
CheckObject("Minion", selectedMinions);
}
}
}
break;
case NextClickAction.TargetHostile:
{
hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if ( hit )
{
if ( hit.transform != null )
{
clickedMob = hit.transform.gameObject;
CheckObject("Hostile", selectedHostiles);
}
}
}
break;
default:
{
Debug.Log("why do you have an enum this big");
DeactivateClick();
Debug.LogError("Enum set outside of index. Returned to 0.");
break;
}
}
}
} // end of update
private void CheckObject ( string tag , List<GameObject> mobList)
{
if ( clickedMob.CompareTag(tag) )
{
if ( clickedMob.GetComponent<Animator>() != null )
{
ClickedMobAnimator = clickedMob.GetComponent<Animator>();
switch (ClickedMobAnimator.GetBool("Selected"))
{
case true:
ClickedMobAnimator.SetBool("Selected", false); // Setting the object to have a little box around it when it's selected.
mobList.Remove(clickedMob);
Debug.Log(mobList.Count + " " + clickedMob);
break;
case false:
ClickedMobAnimator.SetBool("Selected", true);
mobList.Add(clickedMob);
Debug.Log(mobList.Count + " " + clickedMob);
break;
}
}
}
}
此代码的输出:
NullReferenceException: Object reference not set to an instance of an object
ClickHandler.CheckObject (System.String tag, System.Collections.Generic.List'[T] mobList) (at Assets/Scripts/ClickHandler.cs:119)
而且我知道在这种情况下该对象不是 null,因为我有一个调试日志打印该对象。就在那里。
由于您的列表是非公开的并且也是非序列化的字段,您不能从检查器分配它们以自动创建新的列表实例,因此在您的 ClickHandler 脚本中添加 Awake 方法,您可以在其中将它们实例化为新的列表对象。
void Awake() {
selectedMinions = new List<GameObject>();
selectedHostiles = new List<GameObject>();
}
或者您可以在申报时做同样的事情
List<GameObject> selectedMinions = new List<GameObject>();
List<GameObject> selectedHostiles = new List<GameObject>();