我还是一个新的程序员,学习如何做到。必须承认我尝试了很多方法,但仍然没有前进。这段代码可能有点复杂,所以试图告诉你它是如何构造的。 我想访问我在状态机状态中为状态创建的字典,这是一个类的实例。 我设计了它,所以我在课堂上有一个状态(玩家可以切换状态),每个州都持有州名,描述,bool是否有敌人,敌人字典(数字和种族列表),以及bool是否有非 - 玩家角色。
添加了一些代码,以便您可以了解它的运行方式/结构。
在添加怪物之前机器工作得很好,现在我按下播放后我得到错误:“NullReferenceException:对象引用未设置为对象的实例 StateController.GetTransitionsAndActions()(在Assets / _Scripts / GameRPG / StateMachines / StateController.cs:169) StateController.Start()(在Assets / _Scripts / GameRPG / StateMachines / StateController.cs:131)“ ......威尔指着国家控制员:Monobehaviour剧本中的那一行:
Debug.Log ("monster.name: " + monster.name);
请记住,我只向您展示我的部分脚本,但应该足以在Unity控制台中调试输出。
public class FunMachine : IStateMachine
{
List<FunMachineState> mStates;
FunMachineState mCurrent;
FunMachineState mExit;
List <Monster> monsterList = new List<Monster> ();
public FunMachine()
{
List <Monster> monsterList = new List<Monster> ();
MonsterManualVol1 monsterManualVol1 = new MonsterManualVol1 (monsterList);
FunMachineState entryHall = new FunMachineState("Grand Entrance", "You are standing in a grand enterance of a castle.\nThere are tables and chairs, but nothing you can interact with.", "Enter the Grand Entrance", true, new Dictionary<int, Monster> (){{7, monsterList.Find(x => x.name.Contains("orc"))}}, false);
// (...) many other similar states here
}
// Hook up doors.
entryHall.Neighbors.Add(staircase);
entryHall.Neighbors.Add(mExit);
// Add them to the collection
mStates = new List<FunMachineState>();
mStates.Add(entryHall);
// Finally set my starting point
mCurrent = entryHall;
#region IStateMachine Overrides
public override IState CurrentState
{
get { return mCurrent; }
}
public override List<FunMachineState> PossibleTransitions()
{
List<FunMachineState> transitionResult = mCurrent.Neighbors;
return transitionResult = mCurrent.Neighbors;
}
public override Dictionary<int, Monster> GetStateMonsters ()
{
Dictionary<int, Monster> result = new Dictionary<int, Monster> ();
List <Monster> monsterList = new List<Monster> ();
MonsterManualVol1 monsterManualVol1 = new MonsterManualVol1 (monsterList);
result = mCurrent.Monsters;
return result;
}
// (...) more code
}
FunMachineState:
public class FunMachineState : IState
{
string mName;
string mDescription;
string mPlayerChoiceButtonText;
bool mEnemies;
bool mNpcs;
Dictionary<int, Monster> mEnemyDictionary;
List<FunMachineState> mNeighbors = new List<FunMachineState>();
public List<FunMachineState> Neighbors { get { return mNeighbors; } }
public Dictionary <int, Monster> Monsters { get { return mEnemyDictionary; } }
public FunMachineState(string mName, string mDescription, string mPlayerChoiceButtonText, bool mEnemies, Dictionary<int, Monster> mEnemyDictionary, bool mNpcs)
{
this.mName = mName;
this.mDescription = mDescription;
this.mPlayerChoiceButtonText = mPlayerChoiceButtonText;
this.mEnemies = mEnemies;
this.mEnemyDictionary = mEnemyDictionary;
this.mNpcs = mNpcs;
}
#region IState Overrides
public override string GetName()
{
Debug.Log ("Here mName runs!");
return mName;
}
public override string GetStateDescriptionText()
{
return mDescription;
}
public override Dictionary<int, Monster> GetStateMonsters()
{
return Monsters;
}
// (...) more code
}
IStateMachine:
public abstract class IStateMachine
{
// List of all possible transitions we can make from this current state.
public abstract List<FunMachineState> PossibleTransitions();
// Get those monsters.
public abstract Dictionary<int, Monster> GetStateMonsters ();
// (...) more code
}
即将状态置:
public abstract class IState
{
public abstract Dictionary<int, Monster> GetStateMonsters ();
// Do something
public abstract void Run();
// (...) more code
}
现在运行它:
public class StateController : MonoBehaviour
{
public StateController stateController;
IStateMachine machine = GetMachine();
private static IStateMachine GetMachine()
{
IStateMachine machine = null;
machine = new FunMachine();
return machine;
}
void Start()
{
if (!machine.IsComplete())
{
Debug.Log("Currently in " + machine.CurrentState);
machine.CurrentState.Run();
Text_main_game_content.text = machine.CurrentState.GetStateDescriptionText();
GetTransitionsAndActions ();
}
public void GetTransitionsAndActions(){
Dictionary<int, Monster> monsterlisting = machine.CurrentState.GetStateMonsters();
if (monsterlisting.Values.Count > 0)
foreach (var monster in monsterlisting.Values) {
Debug.Log ("monster.name: " + monster.name);
}
}
}
// (...) more code
}
我的怪物收藏:
public class Monster
{
public string name, description;
public bool hostile;
public int hitPoints;
public int damage;
public int loot;
public string coin_type;
public Monster (string c_name, string c_description, bool c_hostile, int c_hitPoints, int c_damage, int c_loot, string c_coin_type)
{
name = c_name;
description = c_description;
hostile = c_hostile;
loot = c_loot;
hitPoints = c_hitPoints;
coin_type = c_coin_type;
damage = c_damage;
}
}
public class MonsterManualVol1
{
public MonsterManualVol1 (List <Monster> c_monsterList)
{
List <Monster> monsterList = new List<Monster> ();
monsterList = c_monsterList;
monsterList.Add (goblin);
monsterList.Add (orc);
}
Monster goblin = new Monster("Goblin", "Cute goblin", true, 7, 5, 28, "sz");
Monster orc = new Monster("Orc", "Pretty orc", true, 6, 6, 20, "sz");
}
我真的不知道发生了什么事。试图将该字典转换为列表,但也没有用。
哦,这可以在状态机启动时正确调试。除了公共类FunMachine:IStateMachine:
public class FunMachine : IStateMachine
{
public override List<Monster> MonsterListDebug () {
monsterList = new List<Monster> ();
MonsterManualVol1 monsterManualVol1 = new MonsterManualVol1 (monsterList);
Debug.Log ("monsterList.Count: " + monsterList.Count);
for (int i = 0; i < monsterList.Count; i++)
{
Debug.Log ("Monster name: " + monsterList [i].name +
" Monster description: " + monsterList [i].description +
" Monster hostility: " + monsterList [i].hostile +
" Monster hit points: " + monsterList [i].hitPoints +
" Monster hit damage: " + monsterList [i].damage +
" Monster hit loot: " + monsterList [i].loot + " " + monsterList [i].coin_type);
}
return monsterList;
}
public FunMachine()
{
// (...)
//MonsterListDebug (monsterList);
MonsterListDebug ();
// (...)
}
// (...)
}
我无法从StateController中的实际CurrentState调试它,它正确地运行游戏。调试仅适用于FunMachine类,如上所示。 StateController中的Foreach循环会删除空引用,这是唯一的问题。 Monodevelop没有显示错误。
答案 0 :(得分:2)
修改强>
呃,不太好。你找到了一种诱导bug的方法。你还没有解决问题。好的伙计......我解决了这个问题。 ......我寻找“兽人”,而它只是“兽人”......就是这样。
解决方案不是:
我应该可以搜索“Yabadabadoo”而不是NullReferenceException
。
KMussa的答案得到了解决。 Dictionary<int, Monster>
应该处理空值。修复分为两部分:
monsterlist.Clear()
Monster
类执行第2部分的最佳方法是编写自定义的“MonsterCollection”或“MonsterDictionary”类。然后最简单的修复方法是拒绝空值的Add()
方法。
如果两个部分都没有完成,问题就无法解决。
结束修改
更简单,更清洁的调试。
移动这个......
"Monster name: " + monsterList [i].name +
" Monster description: " + monsterList [i].description +
" Monster hostility: " + monsterList [i].hostile +
" Monster hit points: " + monsterList [i].hitDice +
" Monster hit damage: " + monsterList [i].damage +
" Monster hit loot: " + monsterList [i].loot + " " + monsterList
...转到Monster
并覆盖ToString
。然后:
for (int i = 0; i < monsterList.Count; i++)
{
Debug.Log (monsterList[i].ToString());
}
return monsterList;
......甚至更好,也会覆盖ToString
中的MonsterManualVol1
,然后for
循环就消失了,你就离开了:
Debug.Log(monsterList.ToString());
为ToString
写一个StateController
。当然,这还包括为其属性调用ToString
。
实际上,为所有类编写ToString
并真正清理日志代码。
不需要在构造函数中初始化和设置属性:
public class FunMachine : IStateMachine
{
List <Monster> monsterList = new List<Monster> ();
public FunMachine()
{
List <Monster> monsterList = new List<Monster> ();
}
测试null的字符串参数:
public Monster (string c_name, ...)
{
name = c_name; // could be null
// so:
name = c_name ?? string.Empty;
在Visual Studio中,您是否有Debug |例外......设置?
答案 1 :(得分:2)
很难遵循确切的流程,但我的猜测是问题出在这一部分:
List <Monster> monsterList = new List<Monster> ();
public FunMachine()
{
List <Monster> monsterList = new List<Monster> ();
FunMachineState entryHall = new FunMachineState("...", "...", "...", true,
new Dictionary<int, Monster> (){{7, monsterList.Find(x => x.name.Contains("orc"))}}, false);
//...
}
具体来说,您在构造函数中声明了一个名为monsterList
的类变量和另一个具有相同名称的局部变量 - 在该阶段,两个列表都将是空,所以当你致电monsterList.Find(x => x.name.Contains("orc"))
时,你会回来NULL
;然后你的字典有一个key = 7和value = null
您稍后尝试遍历字典条目并打印怪物名称并获得NullReferenceException