这些是像Npc和NpcTask这样的基类。
public abstract class NpcTask
{
public Npc Npc { get; private set; }
public NpcTask(Npc npc)
{
Npc = npc;
}
public abstract void Update();
}
public abstract class Npc : MonoBehaviour
{
[HideInInspector]
public NavMeshAgent NavMeshAgent;
public NpcTask CurrentTask;
private void InitializeComponents()
{
NavMeshAgent = GetComponent<NavMeshAgent>();
}
protected virtual void Initialize()
{
InitializeComponents();
}
protected abstract void SetDefaultCurrentTask();
public void Log(object text)
{
Debug.Log("[" + name + "] " + text);
}
private void Start()
{
Initialize();
}
private void Update()
{
CurrentTask?.Update();
}
}接下来的类将是上述的具体和抽象的实现,以便为Npc的类提供更大的灵活性。
public class NpcEnemy : Npc
{
protected override void SetDefaultCurrentTask()
{
CurrentTask = new NpcEnemyTaskWander(this);
}
}
public abstract class NpcEnemyTask : NpcTask
{
public new NpcEnemy Npc { get { return base.Npc as NpcEnemy; } }
public NpcEnemyTask(Npc npc) : base(npc)
{
}
}
public class NpcEnemyTaskWander : NpcEnemyTask
{
public NpcEnemyTaskWander(Npc npc) : base(npc)
{
}
public override void Update()
{
// Wandering logic.
Debug.Log("NpcEnemyTaskWander.Update()");
}
}
public class NpcAllie : Npc
{
public List<NpcEnemy> Enemies;
private void Awake()
{
Enemies = new List<NpcEnemy>();
}
protected override void SetDefaultCurrentTask()
{
CurrentTask = new NpcAllieTaskFightEnemies(this);
}
}
public abstract class NpcAllieTask : NpcTask
{
public new NpcAllie Npc { get { return base.Npc as NpcAllie; } }
public NpcAllieTask(Npc npc) : base(npc)
{
}
}
public class NpcAllieTaskFightEnemies : NpcAllieTask
{
public NpcAllieTaskFightEnemies(Npc npc) : base(npc)
{
}
public override void Update()
{
// Fighting logic.
Npc.NavMeshAgent.SetDestination(Npc.Enemies[0].transform.position);
}
}但是这样的玩家将不需要预先编码的战斗逻辑,因为战斗将由玩游戏的人来完成,但仍然需要一个敌人列表,以便稍后知道玩家可以攻击哪些敌人或诸如此类的东西。
public class Player : MonoBehaviour
{
public List<NpcEnemy> Enemies;
private void Awake()
{
Enemies = new List<NpcEnemy>();
}
private void Move()
{
// Whatever used to listen for input to move (just an example).
}
private void Attack()
{
// Whatever used to listen for input to attack (just an example).
}
private void Update()
{
Move();
Attack();
}
}因此,您可以看到,NpcAllies和播放器都有NpcEnemies列表。我认为最可行/最简单的解决办法,是把名单集中在现场的单身人士身上?
我们还可以说,每个敌人都可能有一个目标,可以是玩家,也可以是NpcAllie (我想我需要在这里使用GameObject类才能更通用?),所以玩家和NpcAllie类需要知道他们是目标还是不攻击正确的NpcEnemies。
public class NpcEnemy : Npc
{
public GameObject Target;
protected override void SetDefaultCurrentTask()
{
CurrentTask = new NpcEnemyTaskWander(this);
}
}发布于 2020-05-10 21:18:16
你会把这两类分开。你应该把这看作是一种“有行为”的关系,而不是“是”的关系。
创建一个类Npc和一个类FightingBehaviour。你把他们都加到战斗中去了。如果您需要从Fighter访问Npc中的方法,您将使用GetComponent<Npc>()
FightingBehaviour甚至不必继承MonoBehaviour。
所以你得到了类似的东西:
public interface IFighter
{
GameObject gameObject;
void Shoot();
}
public class PlayerFighter : MonoBehaviour, IFighter
{
FightingBehaviour _FightingBehaviour;
private void Awake()
{
_FightingBehaviour = new FighterBehaviour(this);
}
}
public class FightingBehaviour
{
IFighter _Fighter;
public List<Enemy> Enemies { get; private set; }
public FightingBehaviour(IFighter fighter)
{
_Fighter = fighter;
}
public Enemy GetClosestEnemy()
{
// implement using _Fighter
}
public Enemy GetEnemiesInView()
{
// implement using _Fighter
}
// etc
public Enemy AttackClosestEnemy()
{
var enemy = GetClosestEnemy();
var direction = _Fighter.gameObject.transform.position - enemy.gameObject.transform.position; // get direction to enemy
_Fighter.RotateTo(direction);
_Fighter.Shoot();
}
}发布于 2021-06-07 01:37:43
备选办法:
public class Character : MonoBehavior
{
// put the common behavior here
}
public class NPC : Character
{
}
public class NPCEnemy : NPC
{
}
public class NPCAlly : NPC
{
}
public class Player : Character
{
}https://softwareengineering.stackexchange.com/questions/409972
复制相似问题