【问题标题】:Creating a pushing wall in Unity在 Unity 中创建推墙
【发布时间】:2017-08-30 17:07:24
【问题描述】:

我想在 3D 游戏中创建推墙。这是一个在超级马里奥 64 中推墙的例子

Pushing Walls in Super Mario 64 (Video on Youtube)

这就是我的墙在检查器中的样子

这是贴在推墙上的代码

public class PushingObstacle : MonoBehaviour {

    private Vector3 startPoint; // the current position when loading the scene

    [SerializeField]
    private Vector3 endPoint; // the target point

    [SerializeField]
    private float forwardSpeed; // speed when moving to the end

    [SerializeField]
    private float backwardSpeed; // speed when moving back to start

    float currentSpeed; // the current speed (forward/backward)

    private Vector3 direction; // the direction the wall is moving
    private Vector3 destination; // the target point

    private Rigidbody obstacleRigid; // rigidbody of the wall

    private void Start()
    {
        startPoint = transform.position;
        obstacleRigid = GetComponent<Rigidbody>();
        SetDestination(endPoint); // set the target point
    }

    private void FixedUpdate()
    {
        obstacleRigid.MovePosition(transform.position + direction * currentSpeed * Time.fixedDeltaTime); // start moving

        if (Vector3.Distance(obstacleRigid.position, destination) < currentSpeed * Time.fixedDeltaTime) // set a new target point
            SetDestination(destination == startPoint ? endPoint : startPoint);
    }

    private void SetDestination(Vector3 destinationPoint)
    {
        destination = destinationPoint;
        direction = (destination - transform.position).normalized; // set the movement direction
        currentSpeed = destination == endPoint ? forwardSpeed : backwardSpeed; // set the speed
    }
}

所以当玩家移动到墙壁并稍微触摸它时,墙壁就会飞走。

我可以将墙壁刚体设置为运动学模式。但我希望墙在推动玩家时给玩家增加最小的力量。我怎样才能实现这两种行为(不飞走和对玩家的小力量)?

编辑:

而且我不能将其设置为运动学,因为在墙(立方体)顶部跳跃时,玩家不会相对于墙移动。

【问题讨论】:

  • 你可以增加墙的刚体质量
  • 玩家的质量与墙的质量是多少?
  • 他们都得到了默认质量
  • 正如@Lestat 所说,尝试将墙的质量更改为更高的值,或降低玩家的质量。

标签: c# unity3d


【解决方案1】:

这是一个艰难的过程。但这是我的解决方案:

  • 为了使推墙能够推玩家,它需要一个更大的 质量比它。就我而言,我设置了墙壁Mass = 10 对于字符Mass = 1
  • 推墙是运动学的,不会受到碰撞的影响 使用游戏对象。
  • 推墙是一个空游戏对象的子对象,它将移动它 在无限循环中向前向后。我们需要一个空游戏对象,所以当 孩子跳过平台(并成为平台的孩子) 规模不受影响。
  • Empty GameObject 有一个触发碰撞器,用于检测何时 玩家跳过平台。当这种情况发生时,采取两个行动 地点:

    1. 玩家成为空游戏对象的子对象并移动
      与平台一起,但同时仍可 用键盘输入控制。
    2. 玩家可以随平台运动
  • 当玩家离开平台顶部时,它不再是 Emppy GameObject 的子对象并停止运动

    这是选择了 Empty GameObject 的场景图像,以显示平台顶部的碰撞器:

这里是空游戏对象的检查器

这里是平台的检查员:

这里是播放器的检查器:

最后是脚本。

空游戏对象的脚本(检测玩家是否在平台上方,并在放置在场景中的两个空游戏对象之间移动平台以确定平台的路径)

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


public class Push : MonoBehaviour {

    public Transform target;
    public Transform end;

    bool movingForward = true;

    float speed = 9f;

    bool moving = false;

    // Update is called once per frame
    void Update () {

        if(movingForward)
         {
            //transform.position = new Vector3(transform.position.x + 0.001f, transform.position.y, transform.position.z);
            float step = speed * Time.deltaTime;
            transform.position = Vector3.MoveTowards(transform.position, target.position, step);

            if(transform.position.Equals(target.position))
                movingForward = false;
         }else{
            float step = speed * Time.deltaTime;
            transform.position = Vector3.MoveTowards(transform.position, end.position, step);

            if(transform.position.Equals(end.position))
                movingForward = true;
         }

    }

    void OnTriggerEnter(Collider other)
    {
        print("Something Inside");
        if(other.tag == "Player")
        {
            print("It is the player");
            other.gameObject.GetComponent<Rigidbody>().isKinematic=true;
            other.gameObject.transform.parent = this.transform;
        }
    }

    void OnTriggerExit(Collider other)
    {
        if(other.tag == "Player")
        {
            other.gameObject.GetComponent<Rigidbody>().isKinematic=false;
            other.gameObject.transform.parent = null;
        }
    }

}

现在是移动播放器的脚本

using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public float speed = 6f;
    Vector3 movement;
    Rigidbody playerRigidbody;
    int floorMask;
    float camRaylength = 100f;
    float JumpSpeed = 15f;

    void Awake()
    {
        floorMask = LayerMask.GetMask("Floor");
        playerRigidbody = GetComponent <Rigidbody> ();
    }
    void FixedUpdate()
    {
        float h = Input.GetAxisRaw ("Horizontal");
        float v = Input.GetAxisRaw ("Vertical");

        Move (h, v);
        Turning ();
        if(Input.GetKeyDown(KeyCode.Space))
            Jump();

    }

    void Jump()
    {
        playerRigidbody.isKinematic=false;
        playerRigidbody.AddForce(Vector3.up *JumpSpeed);

    }

    void Move(float h, float v)
    {
        movement.Set(h, 0f, v);

        movement = movement.normalized * speed * Time.deltaTime;

        playerRigidbody.MovePosition (transform.position + movement);
    }

    void Turning()
    {
        Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);

        RaycastHit floorHit;

        if (Physics.Raycast (camRay, out floorHit, camRaylength, floorMask)) {

            Vector3 playerToMouse = floorHit.point - transform.position;
            playerToMouse.y = 0f;

            Quaternion newRotation = Quaternion.LookRotation (playerToMouse);
            playerRigidbody.MoveRotation (newRotation);

        }
    }

    void Animating(float h, float v)
    {
        bool walking = h != 0f || v != 0f;

    }

}

测试一下,如果有什么不清楚的地方告诉我

【讨论】:

    【解决方案2】:

    我相信您的问题是由玩家的质量与墙的质量造成的。确保这些值彼此之间的关系是半现实的。如果你的墙的质量为 1,那么尝试将玩家的质量设置为 0.1,因为显然混凝土墙比你的平均有机生命形式重得多。

    此外,Unity 论坛往往会针对这些类型的问题提供更好的结果。我不认为这是您的代码的问题,只是为正在使用的对象提供值的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      相关资源
      最近更新 更多