对没有对撞机/刚体的玩家进行光线投射

时间:2018-05-27 10:37:30

标签: c# unity3d collision raycasting

我需要的是,如果玩家挡路的话,通过脚本在路径中移动的NPC会停在玩家面前。 这是一场自上而下的2d比赛,有网格运动。 NPC正在向下移动4个细胞,向下移动2个细胞,向上移动4个细胞和2个细胞。我需要的是,如果玩家挡路,它会停在前面并在玩家离开网格时继续。 我不想在播放器上使用对撞机,因为那时我需要一个rigitbody2d,因此,我的移动脚本无效。

这是TileMovementController.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class TileMovementController : MonoBehaviour {

    public enum Direction { Left, Right, Up, Down }; // Direction of movement

    protected Vector3 newPosition; // For movement

    protected virtual Vector3 move(Direction dir, int steps) {
        if (dir == Direction.Left && transform.position == newPosition)
            newPosition += new Vector3(steps * (-1), 0, 0);
        else if (dir == Direction.Right && transform.position == newPosition)
            newPosition += new Vector3(steps, 0, 0);
        else if (dir == Direction.Up && transform.position == newPosition)
            newPosition += new Vector3(0, steps, 0);
        else if (dir == Direction.Down && transform.position == newPosition)
            newPosition += new Vector3(0, steps * (-1), 0);

        return newPosition;
    }
}

PlayerMovementController.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovementController : TileMovementController {

    public float moveSpeed = 2.0f;

    void Start () {
        newPosition = transform.position; // Take the initial position
    }

    private void FixedUpdate() {
        // RayCasts for collisions, ignoring layer 2 (Ignore Raycast)

        if (Input.GetKey(KeyCode.A) && Physics2D.Raycast(transform.position, Vector2.left, 1, ~(1 << 2)).collider == null) { // Left
            newPosition = move(Direction.Left, 1);
        }

        if (Input.GetKey(KeyCode.D) && Physics2D.Raycast(transform.position, Vector2.right, 1, ~(1 << 2)).collider == null) { // Right
            newPosition = move(Direction.Right, 1);
        }

        if (Input.GetKey(KeyCode.W) && Physics2D.Raycast(transform.position, Vector2.up, 1, ~(1 << 2)).collider == null) { // Up
            newPosition = move(Direction.Up, 1);
        }

        if (Input.GetKey(KeyCode.S) && Physics2D.Raycast(transform.position, Vector2.down, 1, ~(1 << 2)).collider == null) { // Down
            newPosition = move(Direction.Down, 1);
        }

        transform.position = Vector3.MoveTowards(transform.position, newPosition, Time.deltaTime * moveSpeed); // Move there
    }
}

和NpcMovementController.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NpcMovementController : TileMovementController {

    // Defines the direction and number of steps in that direction has to move
    [System.Serializable]
    public struct MoveStep {
        public Direction direction;
        public int steps; // Each step is a grid square. 1 step = 1 unit in the grid position

        public MoveStep(Direction direction, int steps) {
            this.direction = direction;
            this.steps = steps;
        }
    }

    public List<MoveStep> path = new List<MoveStep>();
    public float moveSpeed = 2.0f;

    private int nextStepIndex = 0;
    private bool waiting = false;


    void Start () {
        newPosition = transform.position; // Take the initial position
    }

    private void FixedUpdate() {
        if (path.Count > 0) {
            if (Vector3.Distance(transform.position, newPosition) < 0.05f && !waiting) {
                transform.position = newPosition; // Adjust the position to be exactly what it should be

                waiting = true;
                StartCoroutine("wait", 2f);
            } else {
                if (Vector3.Distance(transform.position, newPosition) > 0.05f)
                    transform.position = Vector3.MoveTowards(transform.position, newPosition, Time.deltaTime * moveSpeed);
            }
        }
    }

    IEnumerator wait(float seconds) {
        yield return new WaitForSecondsRealtime(seconds);

        newPosition = move(path[nextStepIndex].direction, path[nextStepIndex].steps);

        if (nextStepIndex == path.Count - 1)
            nextStepIndex = 0;
        else
            nextStepIndex++;

        waiting = false;
    }
}

在NPCMovementController中,我尝试对玩家进行光线投射,但没有碰撞器/装配体,它显然不起作用。如果我连接对撞机/ rigitbody它会检测到播放器,但我无法移动。

1 个答案:

答案 0 :(得分:1)

我曾做过类似的事情,我通过检查玩家的位置是否在代表npc路径的网格方格内来解决。例如。

让我们想象一下npc会这样移动:

(0,0) - &gt; (0,1) - &gt; (0,2) - &gt; (0,3) - &gt; (1,3) - &gt; (2,3) - &gt; (2,2) - &gt; (2,1) - &gt; (2,0) - &gt; (1,0) - &gt; (0,0)循环

因此,根据我的理解,如果npc在(0,0)中,它将在(0,1),(0,2)和(0,3)中检测到播放器。因此,您可以检查网格中的这三个位置,并将它们与玩家的当前位置进行比较,如果匹配,则该玩家位于路径中。

除此之外,还可以使用刚体来移动您的播放器(这样您就可以继续使用光线投射方法)。您可以使用刚体的速度将npc向一个方向移动。

//moveHorizontal and moveVertical can have +1 or -1 values depending on the inputs of the player:
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
rigidbody.velocity = movement * speed;