Need help using spherical collider and raycast to make spherical gravity...

Hello, I’m struggling a bit trying to figure out how to do this… before even trying to implement the raycasting operations I wanted to make a spherical collider marked ‘is trigger’ and execute the raycasting operations ontriggerenter (or ontriggerstay), but my raycasting and physics operations need to be in fixedupdate (while ontrigger is executed on foxedupdate but cant be used inside of it)… I didnt want to rely on raycasting alone due to cost, so I was hoping I might be able to execute it if the trigger condition was met… unless I’m going about this the wrong way? If anyone could point me in the right direction.

Also, before anyone mentions it, I’m restricted to using unity 5.6 and don’t have access to any standard assets (or most other assets, for that matter). But any help is appreciated. Thanks!

Hey!
I don’t know how to help with the specific conditions. But making small planet gravity is pretty easy!
here the sample code to attach a small objects

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

public class grav : MonoBehaviour
{
    // Start is called before the first frame update
    public Transform planet;
    public float Gscale = 5f;
    Vector3 gravitydirection;
    Rigidbody smallrigid;
    void Start()
    {
       
        smallrigid = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void Update()
    {
        gravitydirection = (planet.position - transform.position).normalized;

        smallrigid.velocity += gravitydirection * Gscale;
    }
}

create a sphere without rigidbody,
create small objects with rigidbody(gravity use =false) +collider

attach the script to the small objects, then attach the planet object to the script’s public "planet " object

That seems to want to make my player flop around and kind of twitch around a little bit as it goes. I did have a fair amount of luck with this, now my only issue is that my camera transform.up doesnt match my player’s as it goes around the sphere (and since my movement script relies partly on camera orientation), so long as i hold my inputs down my player y axis matches the cameras (when it should be vice versa), then when I let go of my inputs my player y snaps to where it should be oriented on the sphere from this script (and if i press my inputs again it snaps back to my cameras y axis)… trying to figure out how to make this work but after weeks of trying to get the 3 scrips working together (movement, camera, and gravity) im so so close-

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

public class Gravity : MonoBehaviour {

    public GameObject planet;

    public Transform pivot;

    public float gravity = 9.8f;

    bool onGround = false;

    float distanceToGround;
    Vector3 groundNormal;

    Rigidbody rb;

    // Use this for initialization
    void Start () {
        rb = GetComponent<Rigidbody>();
        rb.freezeRotation = true;
    }
   
    // Update is called once per frame
    void FixedUpdate () {
        RaycastHit hit = new RaycastHit();
        if(Physics.Raycast(transform.position, -transform.up, out hit, 10))
        {
            distanceToGround = hit.distance;
            groundNormal = hit.normal;

            if (distanceToGround <= 0.2f)
            {
                onGround = true;
            }
            else
            {
                onGround = false;
            }
        }

        Vector3 gravDirection = (transform.position - planet.transform.position).normalized;

        if (onGround == false)
        {
            rb.AddForce(gravDirection * -gravity);
        }

        Quaternion toRotation = Quaternion.FromToRotation(transform.up, groundNormal) * transform.rotation;
        transform.rotation = toRotation;

        //pivot.eulerAngles.y = transform.localRotation.y;

        //float desiredYAngle = pivot.eulerAngles.y;
        //pivot.transform.localRotation = Quaternion.Euler(x,y,z);
    }

    private void OnTriggerEnter(Collider collision)
    {
        planet = collision.transform.gameObject;

        Vector3 gravDirection = (transform.position - planet.transform.position).normalized;

        Quaternion toRotation = Quaternion.FromToRotation(transform.up, gravDirection) * transform.rotation;
        transform.rotation = toRotation;

        rb.velocity = Vector3.zero;
        rb.AddForce(gravDirection);
    }
}

The easiest would be addforce -9,82 and have direction of force be vector3 (rb.centerofmass.pos - origoofgavity.pos) add quaternion with orientation if needed, but the psudo above should do the trick. I wont reccomend using velocity rather than force in this case.

See G*(m1-m2)/(r1^2-r2^2)=g the equation may be slightly wrong but if you google it and find something similar you thats the right onr. Point is if you want multiple orbital bodies you need to consider their mass, and centre of mass. Especially if you want a cluster of objects. But its really simple if you just want earth grav, its 9.82 * direction.normalized in an addforce.

I thought the above code was doing what you described between the raycasting and the ontriggerenter (attempting to use only one or the other doesnt work).

I’m not trying to making anything orbit, literally all I want is my player to be able to walk around my sphere with the camera following accordingly in the y axis, but I’ve been unable to make my camera and/or pivot a child of my player without causing issues (because my player movement is in relation to my camera axes, in turn), so I’m just trying to script it the rest of the way since I’m already so close, unless theres a better way to go about it

Edit: Sorry, been screwing with this so much I got a little mixed up and didnt even realize the ‘ontriggerenter’ part of my code doesnt even do anything, when I comment it out my script behaves the same (though oddly enough I added that part because the first part wasnt working on it’s own at the time, but now it is, aside from my camera still not rotating how I need it to)

Well it it only works as long as center of mass is equal to the position of your sphere. And the code can be simplified. I can try to send the thread to my cousin, he has done something like this before, though i’m not sure he didnt just rotate the sphere. In any case have you tried nesting the camera to the player in the hierearchy? If it doesnt work a simp rotation around z should dothe trick, check out the lookat method. Or slerp.

The raycasting method i have above works just fine for my player, the only issue is the camera doesnt reflect the player rotation and the player rotation snaps back and forth between camera rotation on input (since my player movement and rotation is somewhat reliant on my camera and pivot orientations) so if I child them to my player it goes crazy. I’m not worried about slerping it until I get the camera rotation correct in the first place otherwise that’s trying to overcomplicate it a bit before I’ve figured out the basis of it. But I was trying to use the player and camera Y axes (since y is up) but I’ll try messing around with the z axes a bit and see if I have any better luck (since I’ve been stuck on this for like over a month now its not like I have much else to do but keep messing with it anyway lol)

In that case if you have to use the local up, you do that by getting camera.transform.up iirc, but its hard to truly grasp what the camera is doing by your description. In theory you could sync the transforms every late fixed update in the LateFixedUpdate() call. That way you can set it non kinematically to a projected point from a raycast by the end of every frame, and you can then ‘copy’ the local behaviour over by using the properties calculated locally earlier that frame/physics frame, such that you apply the same changes relative to the new position, by simply using the target destination of the raycast and use that point as the relative reference to a local transformation, and reapply that after you move “reset” the camera to the new position, new raycast same ray properties, then reset all the changes in a relative form and Slerp or set the properties, with this psudo-local. Point is you don’t have to mess with a functioning camera, but all you need is to rotate it again relative to the new point, using the raycast as a pseudo parent that both player and camera have equal relation by. So something like this:

PseudoTransform(imaginary made from raycast 1)

Camera
PseudoTransform(imaginary made from raycast 2 identical to raycast 1 but different origin)
Player

Update() something not with physics
FixedUpdate() something with physics
Do gravity

Raycast1 … From player to point A

Save var changes on player relative to A
Save changes of player position change relative camera

LateUpdate() do something no physics at end of frame
LateFixedUpdate()
Do something at the end of physics frame

Move camera by same ammount as player
Raycast 2 same properties as with players raycast
Apply relative changes caused by gravity dir change of player to camera relative to Point B given by raycast 2.

Next frame

This is a bit rough and unedited i apologize, but essentially this gives you a chance to affect the camera the same as the player once a frame, but without interfeering with the script during its actual functionality, and only once every time gravity is calculated anyway, so you dont tank performance. At least in theory i havent tested this myself, but im fairly confident it’ll work, if i understand your problem that is.

Hmm, I think I see what you’re saying. I tried changing the camera.main.transform.up and the pivot.transform.up to the player.transform.up (as well as adding since realistically I want the camera to be at the players transform.up plus the cameras initial transform.up) but I didnt try it in the way I think you’re describing so I’ll mess around with that a bit, thanks!

Also my mistake, I thought Id included the other two scripts in my reply above (the player and camera movement). Here are those as well

6751675–778723–CameraController.cs (1.53 KB)
6751675–778729–RBPlayerMove.cs (1.24 KB)

Actually, now Im not so sure my camera script is even the issue. If I remove it and just make the camera a child of my player object, my player object still behaves the same. Its got to be something with my gravity or player movement script.