3D snake classical moving and tail's following

hi. guys. i’m making a sort of 3d snake game by unity scripts and someone’s guide source.

but i can’t make a snake tail chain and a classical snake’s tail movement.

i want to make a my snake game like a this youtube video.

addedly, i had ever tried the HingeJoint and SmoothFollow Component. but They are not what I wanted.

please help me.

please check my code.


private var desiredBearing: String = 'South';
private var currentBearing: String;
 
var moveSpeed : float = 1.5;
 
 
var gridSize : int = 1;
enum Orientation {Horizontal, Vertical}
var gridOrientation = Orientation.Horizontal;
var allowDiagonals = false;
var correctDiagonalSpeed = true;
private var input = Vector2(0,-1);
 
var myTransform: Transform;

 
var TailPrefab : GameObject;
var ApplePrefab : GameObject;

private var counter = 0;	
private var lastChain : GameObject = null;

     
function Awake()
{
    myTransform = transform;
}
 
function Start ()
{
	transform.forward = Vector3.Normalize(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")));

    var myTransform = transform;
    var startPosition : Vector3;
    var endPosition : Vector3;
    var t : float;
    var tx : float;
 
    while (true)
    {
        while (input == Vector2.zero)
        {
            GetAxes();
            tx = 0.0;
            yield;
        }
 
		transform.forward = Vector3.Normalize(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")));
     
        startPosition = myTransform.position;
        endPosition = gridOrientation == Orientation.Horizontal?
        
            Vector3(Mathf.Round(myTransform.position.x), 0.0, Mathf.Round(myTransform.position.z)) +
            Vector3(System.Math.Sign(input.x)*gridSize, 0.0, System.Math.Sign(input.y)*gridSize)
            :
            Vector3(Mathf.Round(myTransform.position.x), Mathf.Round(myTransform.position.y), 0.0) +
            Vector3(System.Math.Sign(input.x)*gridSize, System.Math.Sign(input.y)*gridSize, 0.0);
	        t = tx;
        
        while (t < 1.0)
        {
	        myTransform.position = Vector3.Lerp(startPosition, endPosition, t);
	        yield;
	        t += Time.deltaTime * (moveSpeed/gridSize) * (correctDiagonalSpeed  input.x != 0.0  input.y != 0.0? .7071 : 1.0);
  		}

        
        tx = t - 1.0;
        
        GetAxes();
    }
}
 
function Update ()
{
 
    var horizontalMovement = Input.GetAxis("Horizontal");
    var verticalMovement = Input.GetAxis("Vertical");
    
    if (horizontalMovement > 0  currentBearing != 'West')
    {
       desiredBearing = 'East';
    }
    else if (horizontalMovement < 0  currentBearing != 'East')
    {
       desiredBearing = 'West';
    }
    else if (verticalMovement > 0  currentBearing != 'South')
    {
       desiredBearing = 'North';
    }
    else if (verticalMovement < 0  currentBearing != 'North')
    {
       desiredBearing = 'South';
    }
    


	    
	    	    	    

	var r = Random.Range(0, 100);
	
	if(r > 90  GameObject.FindWithTag("apples") == null)
	{
		var range = 3;
		Instantiate(ApplePrefab, Vector3(Random.Range(-range,range), 1, Random.Range(-range,range)), Quaternion(0,0,0,1));
	}
 
}
 
function GetAxes ()
{
    input = Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
 
 
    if (desiredBearing == 'East')
    {
       currentBearing = desiredBearing;
       input.x = 1;
       input.y = 0;
    }
    else if (desiredBearing == 'West')
    {
       currentBearing = desiredBearing;
       input.x = -1;
       input.y = 0;
    }
    else if (desiredBearing == 'North')
    {
       currentBearing = desiredBearing;
       input.y = 1;
       input.x = 0;
    }
    else if (desiredBearing == 'South')
    {
       currentBearing = desiredBearing;
       input.y = -1;
       input.x = 0;
    }
}

function OnCollisionEnter (c : Collision)
{
	if (c.gameObject == null)
	return;
		
	if (c.gameObject.CompareTag("Respawn"))
	{
		Application.LoadLevel("test1");
	}
	
	if (c.rigidbody == null)
	return;
	
	if (c.gameObject.name == "Apple(Clone)")
	{
		var chew : GameObject = null;
		
		if(Random.value > 0.5)
		{
			chew = GameObject.Find("GetSound1");
		}
		else
		{
			chew = GameObject.Find("GetSound2");
		}
		
		chew.audio.Play();
		Destroy(c.gameObject);
		snake_addTail();
		return;
	}
}


function snake_addTail()
{
	if(lastChain == null)
	{
		lastChain = gameObject;
	}
	
	var newChain : GameObject = Instantiate(TailPrefab, lastChain.transform.position - lastChain.transform.forward * 0.5, Quaternion(0,0,0,0));
	
	newChain.transform.rotation = lastChain.transform.rotation;
	
	newChain.name = "Tail " + counter;
	counter++;
}

Hello,

Rather create your tail on runtime instead of of using a prefab. Then do like:

previous_pos = snake_chain[×].position
snake_chain[×].move
snake_chain[x+1].position = previous_pos

thanks for your help.

i know what do you mean. but i can’t apply to my code. can you give me more detailed code?

Sorry but i almost code in c# but you need to store your snake elements into an array and then loop through each elements.

var count = 1;
var max = snakeElements.length;


GameObject firstElement = snakeElements[0];
Vector3 previousPosition = firstElement.transform.position;
firstElement.transform.position += Vector3.Normalize(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")));
while(count<max)
{
GameObject anElement = snakeElements[count];

Vector3 tempPosition = anElement.transform.position;
anElement.transform.position = previousPosition;
previousPosition = tempPosition;

++ count;
}

And please use code tags when posting code next time please. Otherwise its harder to read. You will find an instruction about how to use code tags at http://forum.unity3d.com/threads/143875-Using-code-tags-properly

Hi karlius, check out my 2D Snake Tutorial in my signature. It’s in C# but it will give you some good direction on what your after.

-Raiden

thanks TouchedByAngels raiden.

i changed my unity scripts with your help. and it worked like a 2D snake game.:smile:

but i want to move each a snake tail more smoothly, like other 2D game. (especially looks like a “Nimble Quest”)

now, each a tails move towards front tail, instantly.

how do i do?

please help me~ :frowning:

please check my code.


public var moveSpeed : float = 1.0;					
public var gridSize : int = 1;						

enum Orientation {Horizontal, Vertical}
public var gridOrientation = Orientation.Horizontal;

public var allowDiagonals = false;					
public var correctDiagonalSpeed = true;				

private var desiredBearing: String = 'Down';
private var currentBearing: String; 

private var input = Vector2(0, -1);	
   
public var ApplePrefab : GameObject;
public var TailPrefab : GameObject;
public var SnakeTail : GameObject[];
public var offset : float = 1.0;

private var mainhead : GameObject;

//--------------------
// 
//--------------------      	     	     	   
function Awake()
{
}
 
 
//--------------------
// 
//-------------------- 
function Start ()
{
	mainhead = GameObject.Find("Character_Head 1");
	
	mainhead.gameObject.transform.rotation.eulerAngles =  Vector3(0, 180, 0);	
	
	SnakeTail = new GameObject[0];
        
	// will spawn a segment for each snake tail object
	for(var i = 0 ; i < SnakeTail.Length ; i++)
	{
		Instantiate(TailPrefab, new Vector3(0, 0, 0), Quaternion.identity);
		
		offset += 1.0;
	}

	SnakeTail = GameObject.FindGameObjectsWithTag("Tail");

	transform.forward = Vector3.Normalize(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")));

    var myTransform = transform;
    var startPosition : Vector3;
    var endPosition : Vector3;
	var t : float;
	var tx : float;
	
    while (true)
    {
        while (input == Vector2.zero)
        {
            GetAxes();
            tx = 0.0;
            yield;
        }
 
        startPosition = myTransform.position;
        
        endPosition = gridOrientation == Orientation.Horizontal?
        
            Vector3(Mathf.Round(myTransform.position.x), 0.0, Mathf.Round(myTransform.position.z)) +
            Vector3(System.Math.Sign(input.x)*gridSize, 0.0, System.Math.Sign(input.y)*gridSize)
            :
            Vector3(Mathf.Round(myTransform.position.x), Mathf.Round(myTransform.position.y), 0.0) +
            Vector3(System.Math.Sign(input.x)*gridSize, System.Math.Sign(input.y)*gridSize, 0.0);
	        t = tx;
        
        while (t < 1.0)
        {
			t += Time.deltaTime * (moveSpeed/gridSize) * (correctDiagonalSpeed  input.x != 0.0  input.y != 0.0? .7071 : 1.0);
			myTransform.position = Vector3.Lerp(startPosition, endPosition, t);
			yield;
  		}
        
        tx = t - 1.0;
        
        GetAxes();
    }
}


//--------------------
// Axes Check and Move
//--------------------
function GetAxes ()
{
    input = Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
	    
    if (desiredBearing == 'Right')
    {
		currentBearing = desiredBearing;
		input.x = 1;
		input.y = 0;

		SnakeTail = GameObject.FindGameObjectsWithTag("Tail");
		DrawSnake();
    }
    else if (desiredBearing == 'Left')
    {
		currentBearing = desiredBearing;
		input.x = -1;
		input.y = 0;
       
		SnakeTail = GameObject.FindGameObjectsWithTag("Tail");
		DrawSnake();
	}
    else if (desiredBearing == 'Up')
    {
		currentBearing = desiredBearing;
		input.y = 1;
		input.x = 0;
		
		SnakeTail = GameObject.FindGameObjectsWithTag("Tail");
		DrawSnake();
    }
    else if (desiredBearing == 'Down')
    {
		currentBearing = desiredBearing;
		input.y = -1;
		input.x = 0;
       
		SnakeTail = GameObject.FindGameObjectsWithTag("Tail");
		DrawSnake();
    }
}


//--------------------
// 
//-------------------- 
function Update ()
{
	// Move key Function
    var horizontalMovement = Input.GetAxis("Horizontal");
    var verticalMovement = Input.GetAxis("Vertical");
	    	     		    
    if (horizontalMovement > 0  currentBearing != 'Left')
	{
		desiredBearing = 'Right';
		
		mainhead.transform.rotation.eulerAngles = Vector3(0, 90, 0);	
    }
    else if (horizontalMovement < 0  currentBearing != 'Right')
    {
		desiredBearing = 'Left';
		
		mainhead.transform.rotation.eulerAngles = Vector3(0, 270, 0);	
    }
    else if (verticalMovement > 0  currentBearing != 'Down')
    {
		desiredBearing = 'Up';
       
		mainhead.transform.rotation.eulerAngles = Vector3(0, 180, 0);	
    }
    else if (verticalMovement < 0  currentBearing != 'Up')
    {
		desiredBearing = 'Down';
       
		mainhead.transform.rotation.eulerAngles = Vector3(0, 0, 0);	
    }
		
    // apple respawn
	var r = Random.Range(0, 100);
	
	if(r > 90  GameObject.FindWithTag("apples") == null)
	{
		var range = 3;
		Instantiate(ApplePrefab, Vector3(Random.Range(-range,range), 1, Random.Range(-range,range)), Quaternion(0,0,0,1));
	}
}


//--------------------
// Tail Move and Rotation
//--------------------
function DrawSnake()
{
	for(var i = (SnakeTail.Length - 1); i > 0; i--)
	{
		SnakeTail[i].transform.rotation = SnakeTail[i - 1].transform.rotation;
		SnakeTail[i].transform.position = SnakeTail[i - 1].transform.position;
	}
}


//--------------------
// eating apple
//--------------------
function OnCollisionEnter (c : Collision)
{
	if (c.gameObject == null)
	return;
		
	// Restart
	if (c.gameObject.CompareTag("Respawn"))
	{
		Application.LoadLevel("test1");
	}
	
	if (c.rigidbody == null)
	return;
	
	if (c.gameObject.name == "Apple(Clone)")
	{
		var chew : GameObject = null;
		
		if(Random.value > 0.5)
		{
			chew = GameObject.Find("GetSound1");
		}
		else
		{
			chew = GameObject.Find("GetSound2");
		}
		
		chew.audio.Play();
		
		Destroy(c.gameObject);
		
		SpawnNewTail();
		
		return;
	}
}


//--------------------
// add Tail
//--------------------
function SpawnNewTail()
{
//	Instantiate(TailPrefab, new Vector3(0, 0, 0), Quaternion.identity);
	Instantiate(TailPrefab, new Vector3(SnakeTail[0].transform.position.x, SnakeTail[0].transform.position.y + 1, SnakeTail[0].transform.position.z), Quaternion.identity);
}