【问题标题】:Unity 2D, character will not moveunity 2D,角色不会移动
【发布时间】:2019-10-05 13:13:23
【问题描述】:

所以我遵循了这个指南https://learn.unity.com/tutorial/live-session-2d-platformer-character-controller#5c7f8528edbc2a002053b695

而且我基本上一步一步地遵循了一切。

这里是代码。

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

public class PhysicsObject : MonoBehaviour
{
    public float minGroundNormalY = .65f;
    public float gravityModifier = 1f;
    protected Vector2 targetVelocity;
    protected bool grounded;
    protected Vector2 groundNormal;

    protected Rigidbody2D rb2d;
    protected Vector2 velocity;
    protected ContactFilter2D contactFilter;
    protected RaycastHit2D[] hitBuffer = new RaycastHit2D[16];
    protected List<RaycastHit2D> hitBufferList = new List<RaycastHit2D>(16);

    protected const float minMoveDistance = 0.001f;
    protected const float shellRadius = 0.01f;

    void OnEnable()
    {
        rb2d = GetComponent<Rigidbody2D>();
    }

    // Start is called before the first frame update
    void Start()
    {
        contactFilter.useTriggers = false;
        contactFilter.SetLayerMask(Physics2D.GetLayerCollisionMask (gameObject.layer));
        contactFilter.useLayerMask = true;
    }

    // Update is called once per frame
    void Update()
    {
        targetVelocity = Vector2.zero;
        ComputeVelocity();
    }

    protected virtual void ComputeVelocity()
    {
    }

    void FixedUpdate()
    {
        velocity += gravityModifier * Physics2D.gravity * Time.deltaTime;
        velocity.x = targetVelocity.x;

        grounded = false;

        Vector2 deltaPosition = velocity * Time.deltaTime;
        Vector2 moveAlongGround = new Vector2(groundNormal.y, -groundNormal.x);
        Vector2 move = moveAlongGround * deltaPosition.x;
        Movement(move, false);

        move = Vector2.up * deltaPosition.y;
        Movement(move, true);
    }

    void Movement(Vector2 move, bool yMovement)
    {
        float distance = move.magnitude;
        if (distance > minMoveDistance)
        {
           int count =  rb2d.Cast(move, contactFilter, hitBuffer, distance + shellRadius);
            hitBufferList.Clear();
            for (int i = 0; i < count; i++)
            {
                hitBufferList.Add(hitBuffer[i]);
            }

            for (int i = 0; i < hitBufferList.Count; i++)
            {
                Vector2 currentNormal = hitBufferList[i].normal;
                if (currentNormal.y < minGroundNormalY)
                {
                    grounded = true;
                    if (yMovement)
                    {
                        groundNormal = currentNormal;
                        currentNormal.x = 0;
                    }
                }
                float projection = Vector2.Dot(velocity, currentNormal);

                if (projection < 0)
                {
                    velocity = velocity - projection * currentNormal;
                }
                float modifiedDistance = hitBufferList[i].distance - shellRadius;
                distance = modifiedDistance < distance ? modifiedDistance : distance;
            }
        }
        rb2d.position = rb2d.position + move.normalized * distance;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerPlatformerController : PhysicsObject
{
    public float jumpTakeOffSpeed = 7;
    public float maxSpeed = 7;

    // Start is called before the first frame update
    void Start()
    {
    }

    protected override void ComputeVelocity()
    {
        Vector2 move = Vector2.zero;
        move.x = Input.GetAxis("Horizontal");

        if (Input.GetButtonDown("Jump") && grounded)
        {
            velocity.y = jumpTakeOffSpeed;
        }
        else if (Input.GetButtonUp("Jump"))
        {
            if (velocity.y > 0)
            {
                velocity.y = velocity.y * 0.5f;
            }
        }
        targetVelocity = move * maxSpeed;
    }
}

如果您检查该链接,它可能会添加一些动画,我还没有做到这一点。

所以 atm 我的 char 完全静止不动。下面是图片。

【问题讨论】:

  • 第一次发布顺便说一句,所以添加代码有点奇怪。但基本上它是 2 个独立的脚本。 1 是物理的,然后是玩家控制的 2nd 脚本。因此,当第一个代码到达“使用 system.collections”时,第一个代码结束,第二个开始,所以它不是全部在一个脚本中。习惯了一种更简单的方式,它只是添加 [code] >code
  • 刚刚在两个脚本之间输入了一个空注释&lt;!-- --&gt;。代码必须缩进至少 4 个空格。与您的问题无关,但可以合并最后一个嵌套 if:else if (Input.GetButtonUp("Jump") &amp;&amp; velocity.y &gt; 0) { velocity.y = velocity.y * 0.5f; }。由于 C# 的短路评估,velocity.y &gt; 0 仅在 Input.GetButtonUp("Jump")true 时评估。

标签: c# unity3d game-physics game-development


【解决方案1】:

从 Unity 对象(一般为 MonoBehaviours)继承时,如果您创建新的 Unity 生命周期函数(Start、Awake、Update 等),它将忽略继承类的实现。

在这种情况下,PlayerPlatformerController 实现了一个空的Start,这意味着Start 不会在PhysicsObject 上被调用。

这意味着这段代码不会运行

contactFilter.useTriggers = false;
contactFilter.SetLayerMask(Physics2D.GetLayerCollisionMask (gameObject.layer));
contactFilter.useLayerMask = true;

这可能是一个破坏游戏的问题,因为您正在那里修改与物理相关的参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多