- Home /
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[i].position;
nodes[i].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<Rigidbody>());
}
}
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<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;
}
}
}
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!
Answer by AbandonedCrypt · Feb 16, 2021 at 01:03 PM
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?
Answer by Marcus79 · Feb 16, 2021 at 03:16 PM
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.
Just have a List that you move the last children of your main gameobject from. This will only work if they are in order, meaning your last snake-part is your last child object too.
with Transform.GetChild() you can get a specific child transform and therefore the gameobject. To get the last child gameobject you would do something like
transform.GetChild(transform.childCount -1);
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Sorting a list into multiple smaller lists 1 Answer
For loop does not loop C# 2 Answers
Affect every object in array. 1 Answer
Infinite for loop and List problem 2 Answers