- Home /
Help with Snake like movement algorithm.
Hi all!
i'm trying to create snake like movement that act more like cars convoy then a snake. below the code i came with. it works well as snake but i can't figure out how to keep distance between body parts and keep the movement smooth (like car movement):
this part create a "hidden" snake and take care of controlling it.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MovementController : MonoBehaviour {
public int ConvoyLength=3;
public GameObject HeadObj;
public GameObject SpacerObj;
public GameObject temp;
public static List<Member> Convoy = new List<Member>();
private Vector3 pos;
private float Speed = 10f;
private float xDir;
private float zDir;
private int direction=4;
private float timer;
public float deltaTimer=1f;
// Use this for initialization
void Start () {
xDir=Speed;
HeadObj= Resources.Load ("Prefabs/test/Body") as GameObject;
SpacerObj= Resources.Load ("Prefabs/test/Spacer") as GameObject;
//Convoy.Add (HeadObj);
if(ConvoyLength>1){
Debug.Log ("adding more body");
AddConvoyMembers();
}
pos= new Vector3(0f,0f,0f);
}
// Update is called once per frame
void Update () {
timer+=Time.deltaTime;
//Convoy[0].transform.position=pos;
if(Input.GetKey(KeyCode.UpArrow) ){
xDir= 0f;
zDir=Speed;
direction= 1;
}
if(Input.GetKey(KeyCode.DownArrow) ){
xDir= 0f;
zDir= -Speed;
direction=3;
}
if(Input.GetKey(KeyCode.LeftArrow) ){
xDir= -Speed;
zDir= 0f;
direction=2;
}
if(Input.GetKey(KeyCode.RightArrow) ){
xDir= Speed;
zDir= 0f;
direction=4;
}
// if(Input.GetKeyDown(KeyCode.Space) ){
// ConvoyLength+=1;
// Convoy.Add (BodyObj);
// Convoy[ConvoyLength]= Instantiate (BodyObj,pos,Quaternion.identity) as GameObject;
// }
//Convoy[0].posX = Convoy[0].posX + xDir* Time.deltaTime;
//Convoy[0].posZ = Convoy[0].posZ + zDir* Time.deltaTime;
if(timer > deltaTimer){
Convoy[0].posX = Convoy[0].posX + xDir* Time.deltaTime;
Convoy[0].posZ = Convoy[0].posZ + zDir* Time.deltaTime;
Convoy[0].Dir = direction;
MoveConvoy();
timer-=deltaTimer;
}
}
void AddConvoyMembers(){
float tempPos=0;
Vector3 tempPos2 = new Vector3(tempPos,0f,0f);
for(int i=0;i<ConvoyLength;i++ ){
Convoy.Add (new Member());
}
temp = Instantiate (SpacerObj,tempPos2,Quaternion.identity) as GameObject;
temp.tag="0";
for(int i=1;i<ConvoyLength;i++ ){
Convoy[i] = new Member();
//Convoy[i].posX = tempPos;
if(i%2==0){temp = Instantiate (HeadObj,tempPos2,Quaternion.identity) as GameObject;
temp.tag=i.ToString ();
}
}
}
void MoveConvoy(){
for(int index=ConvoyLength-1;index>0;index--){
Convoy[index].posX = Convoy[index-1].posX;
Convoy[index].posZ = Convoy[index-1].posZ;
Convoy[index].Dir = Convoy[index-1].Dir;
}
}
then i have this code for the body parts, the idea that when i spawn new part with specific tag number it snap to it place on the hidden snake. it also make sure it rotate nicely to the current direction.
using UnityEngine;
using System.Collections;
public class MemberController : MonoBehaviour {
private int TagNumber;
private GameObject nextMember;
private Vector3 pos;
public float TurnSpeed;
// Use this for initialization
void Start () {
TagNumber= int.Parse(this.tag);
//this.transform.position=MovementController.Convoy[TagNumber].transform.position;
}
// Update is called once per frame
void Update () {
pos= new Vector3(MovementController.Convoy[TagNumber].posX,0f,MovementController.Convoy[TagNumber].posZ);
this.transform.position= Vector3.Lerp (this.transform.position,pos,TurnSpeed* Time.deltaTime) ;
//this.transform.position= pos;
if(MovementController.Convoy[TagNumber].Dir==2){
Quaternion target = Quaternion.Euler(0, 180f, 0f);
transform.rotation = Quaternion.Slerp(transform.rotation, target, TurnSpeed * Time.deltaTime);
}
if(MovementController.Convoy[TagNumber].Dir==4){
Quaternion target = Quaternion.Euler(0, 0f, 0f);
transform.rotation = Quaternion.Slerp(transform.rotation, target, TurnSpeed *Time.deltaTime);
}
if(MovementController.Convoy[TagNumber].Dir==1){
Quaternion target = Quaternion.Euler(0, -90f, 0f);
transform.rotation = Quaternion.Slerp(transform.rotation, target, TurnSpeed *Time.deltaTime);
}
if(MovementController.Convoy[TagNumber].Dir==3){
Quaternion target = Quaternion.Euler(0, 90f, 0f);
transform.rotation = Quaternion.Slerp(transform.rotation, target, TurnSpeed *Time.deltaTime);
}
//this.transform.position=MovementController.Convoy[TagNumber].transform.position;
}
}
and this public class for the body hidden parts:
public class Member{
public float posX{ get; set;}
public float posZ{ get; set;}
public int Dir{ get; set;}
}
that's it. not very complected. in the main script i have the variable "Speed" if i set it to high number i do get gaps between parts but the snake moves too fast for my needs. i tried to implement timing to slow it down but then it create jumpy movement.
i'm open to your suggestions...
thanks!!
Answer by haim96 · Apr 28, 2014 at 07:38 PM
while waiting for answer i kept digging and find this link: http://answers.unity3d.com/questions/390009/3d-snake-classical-movement-1.html
with some changes and tweaks it appear to be a much better solution then my. with this i can control the gaps, the body follow nicely and i even made nice rotation for each body part...
Your answer
![](https://koobas.hobune.stream/wayback/20220613143801im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Making a bubble level (not a game but work tool) 1 Answer
Movement Script 1 Answer
my game when built on ios is not smooth. 2 Answers
Smooth transition of object 1 Answer
Help with Snake Like movement 3 Answers