【问题标题】:Unity 2D Platformer - making my enemy not see through wallsUnity 2D Platformer - 让我的敌人看不到墙壁
【发布时间】:2018-10-12 14:32:27
【问题描述】:

基本上我正在寻找一个想法。如何让我的敌人巡逻,但当它到达玩家时 - 它会冲过来并造成伤害,但同时当它到达墙壁并且玩家站在墙壁后面时,它不会攻击。你知道——我不想让他们看穿墙壁。

我已经制作了简单的游戏对象(矩形)来指向它的视线,它工作正常,但我想改进一些。

为了让它更快......我只是想让我的敌人攻击我,但没有看到我穿过墙壁

一些代码:

[DamageFromEnemy.cs]

private void FixedUpdate()
{
    isThatPlayer = Physics2D.OverlapBox(PlayerDetector.position, new Vector2(playerDetectX, playerDetectY), 0, PlayerLayer);

    isThatWall = Physics2D.OverlapBox(PlayerDetector.position, new Vector2(playerDetectX, playerDetectY), 0, gameObject.GetComponent<EnemyScript>().WallLayer);

    if (isThatWall == true && gameObject.GetComponent<EnemyScript>().movingRight == true)
    {
        PlayerDetector.transform.Translate(new Vector3(changePosX, 0, 0));

        //playerDetectX -= PlayerDetector.transform.position.x; // Lowering size. Not Working

        changePosX = (playerDetectX / 2) * (1 / enemyScaleX) + (enemyScaleX / 2) * (1 / enemyScaleX);

        Debug.Log("pozycja x: " + changePosX);
    }

    if (isThatWall == true && gameObject.GetComponent<EnemyScript>().movingRight == false)
    {
        PlayerDetector.transform.Translate(new Vector3(- changePosX, 0, 0));

        //playerDetectX -= PlayerDetector.transform.position.x; // Lowering size. Not Working

        changePosX = (playerDetectX / 2) * (1 / enemyScaleX) + (enemyScaleX / 2) * (1 / enemyScaleX);

        Debug.Log("pozycja x: " + changePosX);
    }

    DetectPlayer();

    AttackTimer();
}
void OnDrawGizmosSelected()
{
    Gizmos.color = Color.blue;
    Gizmos.DrawWireCube(PlayerDetector.position, new Vector3(playerDetectX, playerDetectY));
}

[EnemyScript.cs]

void Update ()
{
    trap = Physics2D.OverlapCircle(ColideDetector.position, detectorRadius, TrapLayer);
    otherEnemy = Physics2D.OverlapCircle(ColideDetector.position, detectorRadius, EnemyLayer);

    if (health <= 0)
    {
        Destroy(gameObject);
    }

    transform.Translate(Vector2.right * speed * Time.deltaTime );

    RaycastHit2D groundInfo = Physics2D.Raycast(groundDetection.position, Vector2.down, distance);

    RaycastHit2D wallInfoR = Physics2D.Raycast(wallDetection.position, Vector2.right, distance, WallLayer);

    RaycastHit2D wallInfoL = Physics2D.Raycast(wallDetection.position, Vector2.left, -distance, WallLayer);


    if (groundInfo.collider == false || trap == true || otherEnemy == true || wallInfoR == true || wallInfoL == true)
    {
        if(movingRight == true)
        {
            transform.eulerAngles = new Vector3(0, -180, 0);
            movingRight = false; 
        }
        else
        {
            transform.eulerAngles = new Vector3(0, 0, 0);
            movingRight = true;
        }
    }
}

Some Gif Feedback

最后 gifs 帧你可以看到它有时会出错。

    public PlayerControls player;
public LayerMask WallLayer;

player = FindObjectOfType<PlayerControls>();
        RaycastHit2D checkWallsToHero = Physics2D.Raycast(wallToHeroRay.position, player.transform.position, 150,WallLayer);

    if (checkWallsToHero == true)
    {
        playerCheck = false;
    }

    void OnDrawGizmosSelected()
{
    Gizmos.color = Color.blue;
    Gizmos.DrawWireCube(PlayerDetector.position, new Vector3(playerDetectX, playerDetectY));
    Gizmos.DrawLine(wallToHeroRay.position, player.transform.position);
}

[新代码示例 - 可能是错误的]:

isThatPlayer = Physics2D.OverlapBox(PlayerDetector.position, new Vector2(playerDetectX, playerDetectY), 0, PlayerLayer);

    isThatWall = Physics2D.OverlapBox(PlayerDetector.position, new Vector2(playerDetectX, playerDetectY), 0, gameObject.GetComponent<EnemyScript>().WallLayer);


    RaycastHit2D checkWallsToHero = Physics2D.Raycast(wallToHeroRay.position, player.transform.position, 0, gameObject.GetComponent<EnemyScript>().WallLayer);

    if (checkWallsToHero.collider != true /*&& isThatPlayer == true*/)
    {
        Debug.Log("Pierwszy state");
        Debug.Log(checkWallsToHero.collider);

        //Debug.Log(isThatPlayer);
        //Debug.Log("Hit: " + checkWallsToHero.collider.gameObject.name);

        playerCheck = false;
        enemyAttackReady = false;
        coolDownTimer = 0;

        enemyAttackCD = 0;
    }
    else if (checkWallsToHero.collider == true && isThatPlayer == true)
    {
        Debug.Log(checkWallsToHero.collider);
        Debug.Log("Drugi state");
        ReadyToAttack(); //charging enemy
        DetectPlayer(); //bool to true when OverlapBox hits player

        AttackTimer(); //cd between enemy attacks
    }

【问题讨论】:

  • ...光线从敌人投射到玩家身上,看看你是否击中玩家而不是墙壁?
  • 好的,感谢重播,我会尝试这个想法
  • 我编辑了我的原始问题,有人可以检查一下吗?好像效果不太好
  • 我在 Unity 中也遇到这样的错误:NullReferenceException:对象引用未设置为对象的实例 DamageFromEnemy.OnDrawGizmosSelected ()(在 Assets/Scripts/Enemy/DamageFromEnemy.cs:102) UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr) 它发送给我: void OnDrawGizmosSelected()...
  • @Draco18s 这个主意很好,效果很好。谢谢你。我对那个 NullReferenceException 有疑问......如果有人知道我能做些什么,请告诉(除了评论整行 - 因为评论解决了问题)

标签: unity3d


【解决方案1】:
if (Physics2D.Raycast2D
(wallToHeroRay.position,player.transform.position,out hit,10)
 &&hit.transform.gameObject.tag == "Player") 
     {                       
         RayHit = true;  
     }
else {             
         RayHit = false;
     }

要使用它,你必须将你的播放器标记为“播放器”,然后你的射线只会在它击中播放器本身而不是墙壁时才会击中你

编辑: 这是我按照@Draco18s 在 cmets 中的想法拼凑起来的代码,如果它适合你,请告诉他谢谢。我只是觉得这很有意义,他应该把它作为答案

【讨论】:

  • 基本正确:您使用了一个 RaycastHit 对象 (hit),但您从未将其作为 out 对象传递给 raycast 方法。
  • 一如既往,你是男人。你认为我需要提到RayHit 本身就是一个布尔值吗?哈哈。我想它会被推断出来,但有时我太着急回答了。
  • 我不得不将其更改为:if (Physics2D.Raycast(wallToHeroRay.position, player.transform.position, 10) &amp;&amp; player.transform.gameObject.tag == "Player")。没有现有的 Raycast2D,我将 hit. 更改为 player.。在为 RayHit 创建 bool 对其进行测试后,总有正确的陈述
  • 你的墙上有碰撞器对吗?哈哈。尝试减少10,如果我没记错的话,那就是范围。英雄雷的墙是什么?比如你从哪里投射光线?它应该来自敌人本身的变换,即enemy.position,该变量使您看起来像是从墙上投射它
  • @Vanethrane 使它更复杂:pastebin.com/D321EduL giphy.com/gifs/fjxcnpCSpHQvDoqMoD >顺便说一句,有 2 个链接,是的,我有对撞机,也缩小了范围。正如你所看到的,光线严格来说是从“敌人”射向玩家。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多