- Home /
2D Platformer with custom physics Object - jumping issue
Hello there :)
I am quite new to unity and coding in general and I am working currently on a 2D-Super-Mario-Like-Platformer Game. I have build an own physics Object with this Unity Tutorial (https://www.youtube.com/playlist?list=PLX2vGYjWbI0SUWwVPCERK88Qw8hpjEGd8) , because it looked promising for exactly the purpose i needed.
Unfortunately I have one issue with my jumping control: When the player jumps and lands on the same level (from Ground to Ground) it behaves as intended. But when i jump on a higher level (e.g. a Plattform) my Player does make another small jump right after landing. As far as I have seen it in a small scene in the youtube Video, the tutor had the very same issue there, but did not notice (or mention) it.
I assume the issue is burried somewhere in the physics Object:
public float minGroundNormalY = 0.65f;
public float gravityModifier = 1f;
public Vector2 targetVelocity;
public bool grounded;
protected Vector2 groundNormal;
public Vector2 velocity;
protected Rigidbody2D rb2d;
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;
private 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;
groundNormal = new Vector2(0f, 1f);
}
// Update is called once per frame
void Update()
{
targetVelocity = Vector2.zero;
ComputeVelocity();
}
protected virtual void ComputeVelocity()
{
}
private 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);
}
public 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;
}
But maybe it is within my player controller:
public float maxSpeed = 7;
public float jumpTakeOffSpeed = 7;
public bool isGrounded = false;
private SpriteRenderer spriteRenderer;
private Animator animator;
public AudioSource jumpSmall;
public AudioSource jumpBig;
void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer> ();
animator = GetComponent<Animator> ();
}
protected override void ComputeVelocity()
{
Vector2 move = Vector2.zero;
move.x = Input.GetAxis("Horizontal");
animator.SetFloat("Speed", Mathf.Abs(move.x));
if (Input.GetButtonDown("Jump") && grounded)
{
velocity.y = jumpTakeOffSpeed;
jumpBig.Play();
}
else if (Input.GetButtonUp("Jump"))
{
if (velocity.y > 0)
velocity.y *= 0.5f;
}
bool flipSprite = (spriteRenderer.flipX ? (move.x > 0.01f) : (move.x < -0.01f));
if (flipSprite)
{
spriteRenderer.flipX = !spriteRenderer.flipX;
}
targetVelocity = move * maxSpeed;
}
I am completely lost and any help would be very much appreciated :) Thanks Folks!
if you are new to all this you really should just use standard unity stuff, this code looks really over complicated. A rigidbody has its own velocity, gravity everything.. what you did here was reinvent the wheel.. Sometimes people want to do that.. I implemented my own gravity.. but I built it on unity physics..
Hi, thanks for the answer! True, i also thought of leaving all this custom stuff behind and working only with the basic unity stuff. But on the other hand, i really want my game to feel like a 2d Plattformer game and i have read several threads, that it is not the best idea for those games to rely on basic unity 2d physics.