一个游戏对象总是先击中另一个

问题描述 投票:0回答:1

首先,我为在这里抛出这么多代码而道歉。虽然我认为可能有 5% 对这个问题很重要,但我宁愿不遗余力。

我对 Unity 比较陌生,我正在制作一个游戏原型,你可以在其中放置军队与另一个玩家,他们在类似于 Mage 和 Monsters 的 2D 平面上战斗。

我正在用两个单元进行测试,每队一个,似乎无论如何,第 2 队总是先击中并且总是赢得战斗 - 没有可变性。虽然我打算增加暴击率等等,但如果 Team2 总是先击中,他们就有先天优势。

这些单位共享完全相同的统计数据。

我尽我所能确保两个单元同时初始化,并且在这种情况下它们不会启动。然而,无论 Unit2(Team2 的)是什么,总是先开始,先命中,因此获胜。

这是我的 BaseUnit 代码,它是 this repo:

public class BaseUnit : MonoBehaviour
{

    public UnitData unitData;

    public int baseHealth;
    public int health;
    public int level;
    
    public int damage;
    public float range;
    public float attackSpeed;
    public float movementSpeed;

    public Team myTeam;
    public bool IsReady = false;
    public bool IsPlaying = false;
    protected BaseUnit currentTarget = null;

    protected bool HasEnemy => currentTarget != null;
    protected bool IsInRange => currentTarget != null && Vector3.Distance(this.transform.position, currentTarget.transform.position) <= range;
    
    protected bool dead = false;
    protected bool canAttack = true;
    protected float waitBetweenAttack;

    void Start()
    {
        baseHealth = unitData.health;
        health = baseHealth;
        level = unitData.level;

        damage = unitData.damage;
        range = unitData.range;
        attackSpeed = unitData.attackSpeed;
        movementSpeed = unitData.movementSpeed;

        UnitManager.Instance.OnRoundStart += OnRoundStart;
        UnitManager.Instance.OnRoundEnd += OnRoundEnd;
        UnitManager.Instance.OnUnitDied += OnUnitDied;

        IsReady = true;
    }

    protected virtual void OnRoundStart() {
        Debug.Log(gameObject.name + " OnRoundStart!");
        IsPlaying = true;
    }
    protected virtual void OnRoundEnd() { }
    protected virtual void OnUnitDied(BaseUnit diedUnit) { }

    protected void FindTarget() {
        var allEnemies = UnitManager.Instance.GetUnitsAgainst(myTeam);
        float minDistance = Mathf.Infinity;
        BaseUnit entity = null;
        foreach (BaseUnit be in allEnemies) {
            if (Vector3.Distance(be.transform.position, this.transform.position) <= minDistance) {
                minDistance = Vector3.Distance(be.transform.position, this.transform.position);
                entity = be;
            }
        }

        currentTarget = entity;
    }

    protected void GetInRange() {
        if (Mathf.Abs(Vector3.Distance(currentTarget.transform.position, this.transform.position)) > range) {
            var step = movementSpeed * Time.deltaTime;
            this.transform.position = Vector3.MoveTowards(this.transform.position, currentTarget.transform.position, step);
        }
    }

    public void TakeDamage(int incomingDamage) { // Maybe add damage type eventually
        baseHealth -= incomingDamage;

        if (baseHealth <= 0 && !dead) {
            dead = true;
            UnitManager.Instance.UnitDead(this);
        }
    }

    protected virtual void Attack() {
        if (!canAttack) {
            return;
        }

        waitBetweenAttack = 1 / attackSpeed;
        StartCoroutine(WaitCoroutine());
    }

    IEnumerator WaitCoroutine()
    {
        canAttack = false;
        yield return new WaitForSeconds(waitBetweenAttack);
        canAttack = true;
    }
}

My MeleeUnit 这是每个单位使用的类别:

public class MeleeUnit : BaseUnit
{
    protected override void OnRoundStart() {
        base.OnRoundStart();

        Debug.Log("Melee OnRoundStart for " + gameObject.name);

        FindTarget();
    }

    public void Update() {
        if (!IsPlaying) {
            return;
        }
        
        if (!HasEnemy) {
            FindTarget();
        }

        if (IsInRange) {
            if (canAttack) {
                Attack();
                currentTarget.TakeDamage(damage);
            }
        }
    }

    public void FixedUpdate() {
        if (!IsPlaying) {
            return;
        }

        if (!HasEnemy) {
            return;
        }

        if (!IsInRange) {
            GetInRange();
        }
    }
}

最后是 UnitManager 类:

public class UnitManager : Manager<UnitManager>
{

    private string teamOneTag = "Team1";
    private string teamTwoTag = "Team2";

    public List<BaseUnit> teamOne = new List<BaseUnit>();
    public List<BaseUnit> teamTwo = new List<BaseUnit>();

    public bool IsPlaying = false;
    
    public Action OnRoundStart;
    public Action OnRoundEnd;
    public Action<BaseUnit> OnUnitDied;

    private void Start()
    {
        Debug.Log(gameObject.name + " starting");
        PopulateTeam(teamOne, teamOneTag);
        PopulateTeam(teamTwo, teamTwoTag);

        StartCoroutine(WaitForAllObjectsToBeReady());
    }

    private bool UnitsAreReady() {
        foreach (BaseUnit unit in teamOne) {
            if (!unit.IsReady) {
                return false;
            }
        }
        foreach (BaseUnit unit in teamTwo) {
            if (!unit.IsReady) {
                return false;
            }
        }

        return true;
    }

    IEnumerator WaitForAllObjectsToBeReady()
    {
        while (!UnitsAreReady()) {
            Debug.Log("Waiting for 0.5 seconds.");
            yield return new WaitForSeconds(0.5f);
        }
        Debug.Log("Invoking OnRoundStart.");
        OnRoundStart?.Invoke();
    }

    public void UnitDead(BaseUnit unit) {
        teamOne.Remove(unit);
        teamTwo.Remove(unit);

        Debug.Log("Deleting " + unit.gameObject.name);

        OnUnitDied?.Invoke(unit);

        Destroy(unit.gameObject);
    }

    private void PopulateTeam(List<BaseUnit> team, string tag) {
        var teamUnits = GameObject.FindGameObjectsWithTag(tag);
        foreach (var unit in teamUnits) {
            team.Add(unit.GetComponent<BaseUnit>());
        }
    }

    public List<BaseUnit> GetUnitsAgainst(Team against) {
        return against == Team.Team1
            ? teamTwo : teamOne;
    }
}

关于如何正确处理此类事情的任何意见,以便哪支球队可能获胜存在一些差异?

谢谢

unity3d
1个回答
0
投票

也许您可以尝试添加 3 或 4 个团队,看看会发生什么。我仍在阅读代码(如果您的团队成长或遇到问题,您可以为自己和其他任何人添加一些评论)但是如果您可以像这样进行一些故障查找,也许您可以弄清楚发生了什么。

如果你确实添加了 4 个团队并且轮次顺序是 4,3,2,1 那么我会假设这些单位是按升序初始化的,然后调用 WaitForAllObjectsToBeReady() 协程并且从中返回的顺序被取消(因为1 首先调用它,然后是 2,然后是 3,然后是 4,一旦 4 准备就绪,它就位于列表的顶部,是最近准备好的)?

© www.soinside.com 2019 - 2024. All rights reserved.