攻击角色前方的敌人

Attack enemy in front of character

我有自动攻击系统,可以攻击范围内的敌人。问题是我不想攻击我身后的敌人,而只想攻击前面的敌人,所以我使用了 Physics.Raycast 并且当我的对撞机触发器内有 1 个敌人时它工作正常但当有更多(假设其中 2 个)时,一个敌人在后面,一个在前面,首先我检查光线投射,它返回真值,但由于我身后的敌人先进入对撞机,我的法术正在施放到它的位置。那么我怎样才能对我面前的物体施法(获得位置)呢?

这是我用来施法的代码:

public void castSpell(GameObject caster, GameObject other, float duration)
{
    var fwd = transform.TransformDirection(Vector3.forward);
    if(castOnlyForward && !Physics.Raycast(transform.position, fwd, 10))
    {
        return;
    }
    Debug.Log("ON");    
    if(animationEnabled)
    {
        foreach(var a in animator)
        {
            foreach(var b in a.bools)
            {
                a.animator.SetBool(b.parameterName, b.parameterValue);
            }
            foreach(var i in a.ints)
            {
                a.animator.SetInteger(i.parameterName, i.parameterValue);
            }
            foreach(var f in a.floats)
            {
                a.animator.SetFloat(f.parameterName, f.parameterValue);
            }
        }
    }

    GameObject Temporary_Spell_Handler;
    Temporary_Spell_Handler = Instantiate(_Spell, Spell_Emitter.transform.position, Spell_Emitter.transform.rotation) as GameObject;


    //Add Spell Script to the casted spell so it handes damage and everything about spells.
    Spell tempSpell = Temporary_Spell_Handler.GetComponent<Spell>();
    tempSpell.caster = caster;

    if(b_lenghtScale)
    {
        float percent = currentDistance / (maxDistance / 100);
        ParticleSystemRenderer pr = Temporary_Spell_Handler.GetComponent<ParticleSystemRenderer>();
        pr.lengthScale = -(((lenghtScale - Math.Abs(pr.lengthScale)) / 100) * percent);
        Vector3 newScale = new Vector3();
        newScale.x = (maxScale.x / 100) * percent;
        newScale.y = (maxScale.y / 100) * percent;
        newScale.z = (maxScale.z / 100) * percent;

        Temporary_Spell_Handler.transform.localScale = newScale;
    }

    if(lookAtEnemy)
    {
        if(other.transform.parent != null && other.transform.parent.gameObject.tag == "pivotChange")
        {
            Temporary_Spell_Handler.transform.LookAt(other.transform.parent.gameObject.transform);
        }
        else
        {
            Temporary_Spell_Handler.transform.LookAt(other.transform);
        }
    }

    Destroy(Temporary_Spell_Handler, duration);
}

这里我投castSpell:

void OnTriggerStay(Collider col)
{
    if(caster.tag == "Player")
    {
        if(CharacterCommands.autoAttacking)
        {
            if(enemiesTags.Contains(col.tag))
            {
                if(!paused)
                {
                    currentDistance = Vector3.Distance(caster.transform.position, col.transform.position);
                    StartCoroutine(Repeat(castSpellEveryNSeconds, () => { castSpell(caster, col.gameObject, spellDuration); }));
                }
            }
        }
    }
    else
    {
        if(frequentlyCastSpell)
        {
            if(enemiesTags.Contains(col.tag))
            {
                if(!paused)
                {
                    currentDistance = Vector3.Distance(caster.transform.position, col.transform.position);
                    StartCoroutine(Repeat(castSpellEveryNSeconds, () => { castSpell(caster, col.gameObject, spellDuration); }));
                }
            }
        }
    }
}

如果您还需要什么,请告诉我。

分析:

如果内部有多个碰撞器,OnTriggerStay 每帧调用多次。

然后您的代码启动 2 个调用

的协程
castSpell(caster, ...

因此,由于施法者在两种情况下都是相同的,因此第二次协程调用可能会覆盖第一个,因此总是对其中一个而不是两者施法。

我的建议:

你伪造了一些视场系统。在启动协同程序之前,您检查 player.transform.forward 中的 Vector3.Angle 是否与连接玩家和敌人位置的向量向量相对应。也就是说,只是区别:player.transform.position - enemy.transform.position - 或者在你的情况下,collider.transform.position 代表敌人。

您可能需要在减法中切换操作数,现在无法测试。

我脑子里的代码:

float angle = Vector3.Angle(player.transform.forward, player.transform.positon - collider.transform.position);
Debug.Log("the angle is: " + angle);
if(angle > -45 && angle < 45){
    // start your spell casting coroutine here
}

确保在测试时阅读控制台,我不是 100% 确定角度值将如何产生。尤其是 0 左右。

您要做的就是按照说明 here 计算点积。这是一个更可靠的解决方案,而不是使用可能导致奇怪行为的角度。