Moving rigidbody from one list to another

Hi guys,

I’m still a beginner in Unity and I have been pondering over this issue for a long time. Time to ask for help!

Hopefully I can explain my problem properly. I’m currently building a Snake game (based on the old Nokia snake), where every time the snake eats a fruit it gets longer. This is done by adding a node to the tail, which is stored in a list. This works perfectly fine, but what I am trying to do is to remove some of the nodes from the tail (so from the list, reason being so the nodes stay behind on the playing board in the game ) and add them to another list to create an independency from the snake, so the snake can eat its own body therefore adding a new gameplay element to the game.

The problem is that I’m not sure how to even approach this issue. The most logical thing I could come up with (and this might even be up for debate) is to iterate over the list with a for loop and get the elements in the nodes list, then transfer them to another list (thus removing them from the nodes list so the Snake gets smaller). It’s working somewhat with the coroutine I created, but the desired effect is not there yet.

Here’s my script:

using Munnica.MambaMover.Stats;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;


namespace Munnica.MambaMover.Control
{
    public class PlayerController : MonoBehaviour
    {
        [Header("Speed Adjuster:")]
        [SerializeField] float stepLength = 0.2f;


        public float movementFrequency = 0.2f;

        [Header("Time in Game:")]
        [SerializeField] float timeAdjuster;

        [Header("Prefabs:")]
        [SerializeField] GameObject tailPrefab;

        private float counter;
        private bool move;

        PlayerDirection direction;

        AudioManager audioManager;
     

        private List<Vector3> delta_Position;

        
        public List<Rigidbody> nodes;


        private List<Rigidbody> newNodes;

        private Rigidbody main_Body;

        private Rigidbody head_Body;

        private Transform tr;

        private bool create_Node_At_Tail;

        private bool remove_Node_From_Tail;
        private bool xIsPressed;



        // Start is called before the first frame update
        void Awake()
        {
            
            audioManager = FindObjectOfType<AudioManager>();
            
            tr = transform;
            main_Body = GetComponent<Rigidbody>();

            InitSnakeNodes();
            InitPlayer();

            delta_Position = new List<Vector3>()
        {
            new Vector3(-stepLength, 0f, 0f),  // -x = left
            new Vector3(0f, 0f, stepLength),  // y = up
            new Vector3(stepLength, 0f, 0f),  // x = right
            new Vector3(0f, 0f, -stepLength) // -y = down
        };
        }

        // Update is called once per frame

        private void Update()
        {
            xIsPressed = Input.GetKeyDown(KeyCode.X);
            RemoveNodeFromTail();
            CheckMoveFrequency();
        }


        private void FixedUpdate()
        {            
            if (move)
            {
                move = false;
                audioManager.PlaySfxNoPitch(2);
                Move();
            }
            else
            {
                return;
            }            
        }


        public bool CreateNodeAtTail()
        {
            create_Node_At_Tail = true;
            return create_Node_At_Tail;
        }

        public void RemoveNodeFromTail()
        {
            if (xIsPressed)
            {                
                StartCoroutine(RemoveNodeCoroutine());              
            }
        }


        IEnumerator RemoveNodeCoroutine()
        {
            for (int i = 4; i < nodes.Count; i++)

            {

                newNodes = new List<Rigidbody>();

                newNodes.Add(tr.GetChild(1).GetComponent<Rigidbody>());
                newNodes.Add(tr.GetChild(2).GetComponent<Rigidbody>());
                newNodes.Add(tr.GetChild(3).GetComponent<Rigidbody>());
                newNodes.Add(tr.GetChild(4).GetComponent<Rigidbody>());

                
                nodes.Remove(nodes[1]);
                nodes.Remove(nodes[2]);
                nodes.Remove(nodes[3]);
                nodes.Remove(nodes[4]);

                nodes.ToList(newNodes.ToList<Rigidbody>());



                //nodes.ToArray()

                yield return new WaitForSeconds(.2f);

                foreach (Rigidbody rb in newNodes)
                {
                    rb.GetComponent<Renderer>().material.color = Color.black;
                    
                }

            }
        }

        public float DecreaseMovementFrequency(float frequency)
        {
            movementFrequency -= frequency;
            return movementFrequency;
        }

        public float IncreaseMovementFrequency(float frequency)
        {
            movementFrequency += frequency;
            return movementFrequency;
        }

        public float CheckMovementFrequency()
        {
            return movementFrequency;
        }

        private void InitSnakeNodes()
        {
            nodes = new List<Rigidbody>();

            nodes.Add(tr.GetChild(0).GetComponent<Rigidbody>());
            nodes.Add(tr.GetChild(1).GetComponent<Rigidbody>());
            nodes.Add(tr.GetChild(2).GetComponent<Rigidbody>());
            

            head_Body = nodes[0];
        }

        private void InitPlayer()
        {
            SetDirectionRandom();

            switch (direction)
            {
                case PlayerDirection.RIGHT:

                    nodes[1].position = nodes[0].position - new Vector3(Metrics.NODE, 0f, 0f);
                    nodes[2].position = nodes[0].position - new Vector3(Metrics.NODE + 1.5f, 0f);
                    print("RIGHT");
                    break;

                case PlayerDirection.LEFT:

                    nodes[1].position = nodes[0].position + new Vector3(Metrics.NODE, 0f, 0f);
                    nodes[2].position = nodes[0].position + new Vector3(Metrics.NODE + 1.5f, 0f);
                    print("LEFT");
                    break;

                case PlayerDirection.UP:
                    print("UP");
                    nodes[1].position = nodes[0].position - new Vector3(0f, 0f, Metrics.NODE);
                    nodes[2].position = nodes[0].position - new Vector3(0f, 0f, Metrics.NODE + 1.5f);

                    break;

                case PlayerDirection.DOWN:
                    print("DOWN");
                    nodes[1].position = nodes[0].position + new Vector3(0f, 0f, Metrics.NODE);
                    nodes[2].position = nodes[0].position + new Vector3(0f, 0f, Metrics.NODE + 1.5f);

                    break;

            }
        }

        private void SetDirectionRandom()
        {
            int dir_Random = Random.Range(0, (int)PlayerDirection.COUNT);
            direction = (PlayerDirection)dir_Random;
            //direction = PlayerDirection.RIGHT;            
        }

        private void Move()
        {
            Vector3 dPosition = delta_Position[(int)direction];

            Vector3 parentPos = head_Body.position;
            Vector3 previousPos;

            main_Body.position = main_Body.position + dPosition;
            head_Body.position = head_Body.position + dPosition;

            for (int i = 1; i < nodes.Count; i++)

            {
                previousPos = nodes*.position;*

nodes*.position = parentPos;*
parentPos = previousPos;
}

if (create_Node_At_Tail)
{
create_Node_At_Tail = false;
GameObject newNode = Instantiate(tailPrefab, nodes[nodes.Count - 1].position, Quaternion.identity);

newNode.transform.SetParent(transform, true);
nodes.Add(newNode.GetComponent());

}

}

private void CheckMoveFrequency()
{
counter += Time.deltaTime * timeAdjuster;
if (counter >= movementFrequency)
{
counter = 0f;
move = true;

}
}

public void SetInputDirection(PlayerDirection dir)
{
if (dir == PlayerDirection.UP && direction == PlayerDirection.DOWN ||
dir == PlayerDirection.DOWN && direction == PlayerDirection.UP ||
dir == PlayerDirection.RIGHT && direction == PlayerDirection.LEFT ||
dir == PlayerDirection.LEFT && direction == PlayerDirection.RIGHT)
{
return;
}

direction = dir;

ForceMove();
}

private void ForceMove()
{
counter = 0;
move = false;
Move();
}

public float GetMovementFrequency()
{
return movementFrequency;
}

public float SetMovementFrequency(float set)
{
movementFrequency = set;
return movementFrequency;
}

}
}
The code block in question is:
IEnumerator RemoveNodeCoroutine()
{
for (int i = 4; i < nodes.Count; i++)

{

newNodes = new List();

newNodes.Add(tr.GetChild(1).GetComponent());
newNodes.Add(tr.GetChild(2).GetComponent());
newNodes.Add(tr.GetChild(3).GetComponent());
newNodes.Add(tr.GetChild(4).GetComponent());

nodes.Remove(nodes[1]);
nodes.Remove(nodes[2]);
nodes.Remove(nodes[3]);
nodes.Remove(nodes[4]);

nodes.ToList(newNodes.ToList());

//nodes.ToArray()

yield return new WaitForSeconds(.2f);

foreach (Rigidbody rb in newNodes)
{
rb.GetComponent().material.color = Color.black;

}

}
}
So basically I’m trying to move the nodes from the current attached nodes of the Snake to a new list of nodes (newNodes), so I can manipulate the newNodes list by adding extra things to it.
Is this even a logical approach or am I over complicating things??
Any help would be greatly appreciated!

You are only removing the Rigidbody components, why don’t you just remove the gameObjects themselves, or if you want to reuse them later, move them to another reference and set them inactive?

Thanks for taking the time to reply!

I tried to change the list to GameObject but it somehow messes around with the transform. The Snake nodes are positioned as children in the hierarchy and the head of the snake is the main gameobject. I haven’t fully dived into it yet, I need a little more time.

I fiddled around a bit more and this has the result I was looking for, but I’m still trying to move the removed nodes to another list, hoping I could use ToList<> somehow, but I don’t know how to do that.

for (int i = 0; i < nodes.Count; i++)

            {
                newNodes = new List<Rigidbody>();

                if (nodes.Count > 3)
                {                                        
                    nodes.RemoveRange(3, nodes.Count - 3);
                    
                }
             }

I was just curious if that would work, otherwise I’d have to restructure the entire script and its dependencies.