Implementing Custom Raycast Collisions

Hey guys, got a very odd question here.

I’m implementing my own 3d coordinate system for physics calculations, based in doubles, and so far I have everything working. The goal is to keep the player (and any other “rooted” object, like a ship, etc) at the origin for rendering, and then, after physics calculations, place objects relative to the player. This is working.

I then implemented gravity to objects, and this works by having a GravitySimulator that adds velocity to objects every fixed update.

I originally moved objects based on this velocity, but then had issues as collisions don’t work manually setting object positions.

I then thought of raycasting, using the position of the object + radius as the distance, and if the intended movement was larger than a cast that hit, then move the lesser amount, but this doesn’t work? perhaps i’m simply bad with my implementation, but I seriously think maybe this is more complex than I think it is.

Here is what im doing:

``````private void UpdateRendererPosition()
{
Vector3d relativePosition = dposition - playerCoordinateModule.dposition;
transform.position = (Vector3)relativePosition;
}

private void moveObject()
{
Vector3 moveDirection = (Vector3)dvelocity.normalized;
float moveMagnitude = (float)dvelocity.magnitude;

Ray ray = new Ray(transform.position, moveDirection);
RaycastHit hit;

// Draw the ray in the editor for debugging
Debug.DrawRay(transform.position, moveDirection * (moveMagnitude + gravityObject.radius), Color.red);

if (Physics.Raycast(ray, out hit, moveMagnitude + gravityObject.radius))
{
if (hit.distance < 0)
{
hit.distance = 0; // Ensure no negative distance
}

Debug.Log(\$"Raycast hit: {hit.collider.name} at {hit.point}");
Vector3d newVelocity = new Vector3d(ray.direction * hit.distance);
Debug.Log(newVelocity.x + " " + newVelocity.y + " " + newVelocity.z);
dvelocity = newVelocity;
}

dposition += dvelocity * Time.fixedDeltaTime;
UpdateRendererPosition();
}
``````

“UpdateRendererPosition” keeps everything rooted to player and player to origin, but I suspect it is the “root” of the problem

Here is the full class, and gravity implementation class if that helps:

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

public class CoordinateModule : MonoBehaviour
{
public Vector3d dposition, dvelocity;
protected bool rooted = false;
private PlayerCoordinateModule playerCoordinateModule;
private GravityObject gravityObject; // To get the radius

private void Awake()
{
// Find the player
playerCoordinateModule = GameObject.FindWithTag("Player").GetComponent<PlayerCoordinateModule>();
gravityObject = GetComponent<GravityObject>(); // Get the GravityObject component
}

private void Start()
{
// Initially update the renderer position
UpdateRendererPosition();
}

private void FixedUpdate()
{
moveObject();
}

private void UpdateRendererPosition()
{
Vector3d relativePosition = dposition - playerCoordinateModule.dposition;
transform.position = (Vector3)relativePosition;
}

private void moveObject()
{
Vector3 moveDirection = (Vector3)dvelocity.normalized;
float moveMagnitude = (float)dvelocity.magnitude;

Ray ray = new Ray(transform.position, moveDirection);
RaycastHit hit;

// Draw the ray in the editor for debugging
Debug.DrawRay(transform.position, moveDirection * (moveMagnitude + gravityObject.radius), Color.red);

if (Physics.Raycast(ray, out hit, moveMagnitude + gravityObject.radius))
{
if (hit.distance < 0)
{
hit.distance = 0; // Ensure no negative distance
}

Debug.Log(\$"Raycast hit: {hit.collider.name} at {hit.point}");
Vector3d newVelocity = new Vector3d(ray.direction * hit.distance);
Debug.Log(newVelocity.x + " " + newVelocity.y + " " + newVelocity.z);
dvelocity = newVelocity;
}

dposition += dvelocity * Time.fixedDeltaTime;
UpdateRendererPosition();
}

public void rootObject()
{
if (!gameObject.CompareTag("Player"))
{
gameObject.transform.parent = playerCoordinateModule.transform;
}
rooted = true;
// Do not fix the position to zero, just update the renderer
UpdateRendererPosition();
}

public void unRootObject()
{
if (!gameObject.CompareTag("Player"))
{
gameObject.transform.parent = null;
}
rooted = false;
UpdateRendererPosition();
}

public Vector3d getDPosition()
{
return dposition;
}

{
dvelocity += newDVelocity;
}
}
``````

Gravity:

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

public class GravitySimulator : MonoBehaviour
{
GameObject[] gravityAffectedObjects;

private void Start()
{
gravityAffectedObjects = GameObject.FindGameObjectsWithTag("GravityObject");
GameObject player = GameObject.FindWithTag("Player");
GameObject[] newArray = new GameObject[gravityAffectedObjects.Length + 1];
for (int i = 0; i < gravityAffectedObjects.Length; i++)
{
newArray[i] = gravityAffectedObjects[i];
}
newArray[gravityAffectedObjects.Length] = player;
gravityAffectedObjects = newArray;
}

private void FixedUpdate()
{
foreach (GameObject obj in gravityAffectedObjects)
{
foreach (GameObject otherObj in gravityAffectedObjects)
{
if (obj == otherObj) continue;
if (obj == null || otherObj == null) continue;

Vector3d distanceVector = otherObj.GetComponent<CoordinateModule>().getDPosition() - obj.GetComponent<CoordinateModule>().getDPosition();
double sqrDistance = distanceVector.sqrMagnitude;

// Ensure sqrDistance is not zero and not NaN to avoid invalid operations
if (sqrDistance == 0 || double.IsNaN(sqrDistance)) continue;

double forceMagnitude = 1 * (obj.GetComponent<GravityObject>().getMass() * otherObj.GetComponent<GravityObject>().getMass()) / sqrDistance;
Vector3d forceVector = distanceVector.normalized * forceMagnitude;

if (!double.IsNaN(forceVector.x) && !double.IsNaN(forceVector.y) && !double.IsNaN(forceVector.z))
{