繁体   English   中英

如何防止玩家在Unity3d中穿过墙壁

[英]How to prevent a player from moving through walls in Unity3d

我有以下播放器控制器:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

[RequireComponent(typeof(NetworkIdentity))]
public class PlayerController : NetworkBehaviour {
    public Vector3 size = new Vector3(1, 1, 1);
    public float speed = 10;
    public float rotateSpeed = 9;

    private Transform _transform;
    private Map _map;
    private BoxCollider _collider;
    private bool _active = false;

    private Vector3 _lastPosition;
    private bool _isGrounded = false;

    void Start () {
        _transform = transform;
        Messenger.AddListener ("MAP_LOADED", OnMapLoaded);

        _transform.localPosition = new Vector3 (-100, -100, -100);

        gameObject.name = "Player " + gameObject.GetComponent<NetworkIdentity> ().netId.Value;
        _collider = gameObject.GetComponent<BoxCollider> ();
        _map = GameObject.Find ("Map").GetComponent<Map> ();

        _collider.size = size;
    }

    void OnMapLoaded () {
        if (isLocalPlayer) {
            // Hook up the camera
            PlayerCamera cam = Camera.main.GetComponent<PlayerCamera>();
            cam.target = transform;

            // Move the player to the it's spawn location
            _transform.localPosition = _map.GetPlayerSpawn();
        }

        // Set the player as active
        _active = true;
    }

    void Update () {
        if (!isLocalPlayer || !_active) {
            return;
        }

        _lastPosition = _transform.position;

        float transAmount = speed * Time.deltaTime;
        float rotateAmount = rotateSpeed * Time.deltaTime;

        if (Input.GetKey ("up")) {
            transform.Translate (0, 0, transAmount);
        }
        if (Input.GetKey ("down")) {
            transform.Translate (0, 0, -transAmount);
        }
        if (Input.GetKey ("left")) {
            transform.Rotate (0, -rotateAmount, 0);
        }
        if (Input.GetKey ("right")) {
            transform.Rotate (0, rotateAmount, 0);
        }

        if (!_isGrounded) {
            Vector3 down = _transform.TransformDirection(Vector3.down);
            _transform.position += down * Time.deltaTime * _map.gravity;
        }
    }

    void FixedUpdate () {
        //
        // Check what is below us
        //
        Vector3 down = _transform.TransformDirection(Vector3.down);
        RaycastHit[] hits;
        hits = Physics.RaycastAll(_transform.position, down, size.y + 0.001f);

        _isGrounded = false;
        foreach (RaycastHit hit in hits) {
            if (hit.collider.gameObject.tag.ToUpper() == "GROUND") {
                _isGrounded = true;
            }
        }
    }

    void OnTriggerEnter(Collider collider) {
        Debug.Log ("Triggered by " + collider.gameObject.tag.ToUpper ());
        if (collider.gameObject.tag.ToUpper () == "GROUND") {
            transform.position = _lastPosition;
        }
    }

}

Update我将接受用户的输入并移动转换。 FixedUpdate我正在检查播放器是否在地面上并适当设置一个标志。 最后,在OnTriggerEnter我正在检查是否尝试进行任何检查。

如果在OnTriggerEnter碰到某件事,我会尝试将玩家的位置重新设置为一个好位置,但这并没有发生。 我的猜测是因为_lastPosition不是我期望的那样。

有一个更好的方法吗?

使用hardbody.Move(position)而不是transform.Translate(position)

注意:使用transform.translate会导致性能问题,您必须手动处理冲突检测。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM