【发布时间】:2019-10-05 13:13:23
【问题描述】:
而且我基本上一步一步地遵循了一切。
这里是代码。
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
-
刚刚在两个脚本之间输入了一个空注释
<!-- -->。代码必须缩进至少 4 个空格。与您的问题无关,但可以合并最后一个嵌套 if:else if (Input.GetButtonUp("Jump") && velocity.y > 0) { velocity.y = velocity.y * 0.5f; }。由于 C# 的短路评估,velocity.y > 0仅在Input.GetButtonUp("Jump")为true时评估。
标签: c# unity3d game-physics game-development