- Home /
Question by
DamDamDuSixZero · Nov 25, 2019 at 02:54 PM ·
raycastcolliderplatformer
Controller2D - Raycast : Collider sometimes pass through platform
Hello, I try to make my own controller 2d for a platformer, for the moment it's very simple, it's only affected by gravity and it's working most of time buuut sometimes my character pass through the platform :/
I use the Sebastian Lague's tuto for example, with a skinWidth and a raycast lengh determined by character's speed.
If someone have already worked on this and had this kind of error, and have some tips or explanation it would be very nice ! :)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace DDProd.Engine
{
public class Controller_Character2 : MonoBehaviour
{
public float DstBetweenRays = 0.1f;
public float Gravity;
protected Vector2 _CurrentSpeed;
protected Vector2 _MoveAmount;
public LayerMask PlatformMask = 0;
public bool DrawRaycast;
public struct RaycastOrigins
{
public Vector2 topLeft, topRight;
public Vector2 bottomLeft, bottomRight;
public Vector2 centerLeft, centerRight;
public Vector2 centerBottom, centerTop;
}
protected RaycastOrigins _RaycastOrigins;
protected int _HorizontalRayCount;
protected int _VerticalRayCount;
protected float _HorizontalRaySpacing;
protected float _VerticalRaySpacing;
public const float _SkinWidth = .015f;
//private var
protected Transform _Transform;
protected BoxCollider2D _BoxCollider;
protected void Awake()
{
Initialization();
}
protected void Initialization()
{
_BoxCollider = (BoxCollider2D)GetComponent<BoxCollider2D>();
_Transform = transform;
CalculateRaySpacing();
}
protected void Update()
{
_CurrentSpeed.y += Gravity * Time.deltaTime;
UpdateRaycastOrigins();
_MoveAmount = _CurrentSpeed * Time.deltaTime;
BottomCollisions();
_Transform.Translate(_MoveAmount, Space.Self);
_CurrentSpeed = _MoveAmount / Time.deltaTime;
}
void BottomCollisions()
{
float _rayLength = Mathf.Abs(_MoveAmount.y) + _SkinWidth;
bool _rayHaveHit = false;
float _distanceMinimum = 0f;
for (int i = 0; i < _VerticalRayCount; i++)
{
Vector2 _rayOrigin = _RaycastOrigins.bottomLeft + (Vector2.right * (_VerticalRaySpacing * i + _MoveAmount.x));
RaycastHit2D _hit = DDProdDebug.RayCast(_rayOrigin, -Vector2.up, _rayLength, PlatformMask, Color.blue, DrawRaycast);
if (_hit)
{
if (!_rayHaveHit)
{
_distanceMinimum = _hit.distance;
_rayHaveHit = true;
}
else
{
if (_hit.distance < _distanceMinimum)
{
_distanceMinimum = _hit.distance;
}
}
}
}
if (_rayHaveHit)
{
_MoveAmount.y = (_distanceMinimum -_SkinWidth) * -1;
}
}
///-------------------------------------------------------------------------------------------------------------------------------------------------------------------
///------------------------------------------------------------------------- RAYCASTS API ----------------------------------------------------------------------------
///-------------------------------------------------------------------------------------------------------------------------------------------------------------------
public void CalculateRaySpacing()
{
Bounds bounds = _BoxCollider.bounds;
bounds.Expand(_SkinWidth * -2);
float boundsWidth = bounds.size.x;
float boundsHeight = bounds.size.y;
_HorizontalRayCount = Mathf.RoundToInt(boundsHeight / DstBetweenRays);
_VerticalRayCount = Mathf.RoundToInt(boundsWidth / DstBetweenRays);
_HorizontalRaySpacing = bounds.size.y / (_HorizontalRayCount - 1);
_VerticalRaySpacing = bounds.size.x / (_VerticalRayCount - 1);
}
public void UpdateRaycastOrigins()
{
CalculateRaySpacing();
Bounds bounds = _BoxCollider.bounds;
bounds.Expand(_SkinWidth * -2);
_RaycastOrigins.bottomLeft = new Vector2(bounds.min.x, bounds.min.y);
_RaycastOrigins.bottomRight = new Vector2(bounds.max.x, bounds.min.y);
_RaycastOrigins.topLeft = new Vector2(bounds.min.x, bounds.max.y);
_RaycastOrigins.topRight = new Vector2(bounds.max.x, bounds.max.y);
_RaycastOrigins.centerLeft = new Vector2(bounds.min.x, bounds.center.y);
_RaycastOrigins.centerRight = new Vector2(bounds.max.x, bounds.center.y);
_RaycastOrigins.centerBottom = new Vector2(bounds.center.x, bounds.min.y);
_RaycastOrigins.centerTop = new Vector2(bounds.center.x, bounds.max.y);
}
}
}
public static class DDProdDebug
{
public static RaycastHit2D RayCast(Vector2 rayOriginPoint, Vector2 rayDirection, float rayDistance, LayerMask mask, Color color, bool drawGizmo = false)
{
if (drawGizmo)
{
Debug.DrawRay(rayOriginPoint, rayDirection * rayDistance, color);
}
return Physics2D.Raycast(rayOriginPoint, rayDirection, rayDistance, mask);
}
}
Comment
Best Answer
Answer by DamDamDuSixZero · Nov 25, 2019 at 07:38 PM
Sooo I've finally find where it came from, in newer version of Unity you have an option "Auto Sync Transform" which is disabled by default and cause transform modification to not being update at every frame ... So problem solved :'(
Your answer