Snake game with spherical gravity


Here I would like  to share how I made the basic physics mechanics of my game. I was using Unity and some steps in general can be found with quick google search so I'll focus on how these ideas had to be adjusted or changed for my game.

First, lets implement gravity as gravity provided by Unity won't do. Instead I found example of GravityBody-GravityAttractor scripts that do exactly that and are perfect for base of my game.

GravityBody is a simple script that turns off Unity's gravity from rigid body and links this object to attractor. This needs to be added to our snake and its targets.

    void Awake () {
        gravity = FindObjectOfType<GravityAttractorBase>();
        rigidbody = GetComponent<Rigidbody> ();
        rigidbody.useGravity = false;
        rigidbody.constraints = RigidbodyConstraints.FreezeRotation;
    }
    void FixedUpdate () {
        if (gravity)
            gravity.Attract(rigidbody);
    }

Meanwhile attractor applies gravity force to the object in the direction to the center. Additionaly object's Z axis is alligned to always face upwards from center.

    public override void Attract(Rigidbody body) 
    {
        Vector3 gravityUp = (body.position - transform.position).normalized;
        Vector3 localUp = body.transform.up;
        
        // Apply downwards gravity to body
        body.AddForce(gravityUp * gravity);
        // Allign bodies up axis with the centre of planet
        body.rotation = Quaternion.FromToRotation(localUp,gravityUp) * body.rotation;
    }


Now when that's done we can work on our snake.

First, the snake should always be moving straight in a set speed. and be able to turn left or right.

    if (needToTurn)
        rigidbody.MoveRotation(rigidbody.rotation * deltaRotation);      
      
    Vector3 localMove = transform.forward * moveSpeed;
    rigidbody.MovePosition(rigidbody.position + localMove);

For other body parts we'll use 2 lists: bodyParts to store all created body objects, bodyVectors to store snake's previous positions that will be used to move rest of the body.

Now make AddBody() function that will instantiate body parts and add code to snake update function. In update method we want to store snake's transform position to vectors list but we don't need to store more than needed. That's why whe should should remove oldest positions once the list is longer than needed for lenght of our snake and insert new positions at the start of the list. gapLen is used to seperate multiple positions between each segment - its value depends on how fast you are going to move and how big your segments are going to be.

    public void AddBody()
    {
        GameObject bp = Instantiate(bodyPrefab);
        bp.GetComponent<SnakeBody>().gravity = gravityAttractor;
        bodyParts.Add(bp);
    }
// part of Fixed update
    if (bodyVectors.Count > (bodyParts.Count + 1) * gapLen)                 
        bodyVectors.RemoveAt(bodyVectors.Count - 1);             
    bodyVectors.Insert(0, transform.position);
    if (Mathf.RoundToInt(snakeLength) > bodyParts.Count && bodyVectors.Count > (bodyParts.Count + 1) * gapLen)            
        AddBody();
    GameObject lastPart = gameObject; 
    int i = 1;             
    Vector3 lastPos = Vector3.zero;             
    foreach (var item in bodyParts)             
    {                 
        Rigidbody body = item.GetComponent<rigidbody>();                 
        Vector3 pos = bodyVectors[Mathf.Min(i * gapLen, bodyVectors.Count - 1)];                 
        item.transform.position = pos;                 
        Vector3 gravityUp =  item.GetComponent<snakebody>().gravity.GetUpDirection(body.transform.position);              
         item.transform.LookAt(lastPart.transform, gravityUp);                 
        lastPart = item;                 
        i++;             
    }  

In my final build I found that it is best to use float variable for current snake length and create new body part only for each full number. That way it can be fed with things that also give half points.

 Finally, all body parts are placed in their new positions with thier x axis facing at snake head or prevoius sergment and their z axis pointing upwards. The end result should be something like this


Get World Serpent

Buy Now$2.99 USD or more

Leave a comment

Log in with itch.io to leave a comment.