- Home /
Help with Snake Like movement
Hi all,
Simple question, how can I create a movement similar to the original snake but smoother, almost like this: https://www.youtube.com/watch?v=HWpEVyvngNc
I've been working through some other tutorials on movement (I'm still new to c#), i've modified a few but they dont quite get the result i need, here is what i have so far:
using UnityEngine;
using System.Collections;
[RequireComponent (typeof (CharacterController))]
public class Player : MonoBehaviour {
public float rotationSpeed = 450;
public float walkSpeed = 5;
//System
private Quaternion targetRotation;
//Components
private CharacterController controller;
void Start (){
controller = GetComponent<CharacterController>();
}
void Update () {
Vector3 input = new Vector3(Input.GetAxisRaw ("Horizontal"), 0,Input.GetAxisRaw ("Vertical"));
if (input != Vector3.zero) {
targetRotation = Quaternion.LookRotation(input);
//transform.eulerAngles = new Vector3(0f, 90, 0f);
transform.eulerAngles = Vector3.up * Mathf.MoveTowardsAngle(transform.eulerAngles.y, targetRotation.eulerAngles.y,rotationSpeed * Time.deltaTime);
}
Vector3 motion = input;
motion *= (Mathf.Abs (input.x) == 1 && Mathf.Abs (input.z) == 1) ? .7f : 1;
motion += Vector3.up * -8;
controller.Move (motion * Time.deltaTime);
}
}
The movement looks great, except for these problems:
I cant make it so the snake keeps moving after button has been let go, (must always be moving in the direction it is facing)
If the player holds W and D, the player will be able to move diagonally, I do not want this.
Currently the snake does not get bigger and I'm not really interested in integrating that just yet.
Any help would be great, thanks!
Hi! Regarding the second issue, how about making an If statement that If(Input.Get$$anonymous$$eyDown.D & Input.Get$$anonymous$$eyDown.W) do nothing, but else do your movement.
good thought, but I tried it and it doesn't seem to work. I think the fact that it needed an if or statement encase it was W and A seemed to brake that method.
Answer by fafase · Feb 26, 2015 at 12:11 PM
Best way would be to create a queue of nodes.
When you press a key, you define the movement the first should use, that is up/down/left/rigth. Since your level is probably a grid, you get the value of the next position and move your first guy there.
Now you have a queue of node with each of them having a ref to the previous one, all you need to do is move the node towards the position of the previous node. Now there is a trick in that, you do not want to move where the previous is currently or that would lead in diagonal movement, you want each node to move towards the last recorded grid position.
A0 A1 A2 A3
B0 B1 B2 B3
C0 C1 C2 C3
Consider you have the head at A0 and two following nodes (N1 and N2) at B0 and C0, user presses right, Head gets A1 as target and starts moving there, N1 starts moving towards A0 which is the last recorded position of the previous node (the Head), N2 is moving towards B0 which is the last recorded position of the previous node (N1).
This will result in a snake movement which is fine if you use distinct items like in the video, if you need a full length and fluid movement for a snake then you should look into some kinda of curve algorithm like Beziers curve or Catmull rom, looks complex but the function is just plain arithmetic. If you use those with LineRenderer for instance, it will look fluid.
Answer by itsmealex100 · Feb 26, 2015 at 12:38 PM
Okay so i've managed to figure out how to keep the player moving in whichever way they are facing.
simply add the following
public float fSpeed;
void Update() {
transform.localPosition = transform.localPosition + transform.forward * fSpeed * Time.deltaTime;
}
However I still need help keeping the player from facing a diagonal direction, I need him to only turn 90 degrees like snake.
you should focus on creating a grid of positions, then based on the input you get a target position, your head has 3 possible movement based on the 4 positions around it $$anonymous$$us the one where the second node is.
Then you move the head towards that target point and rotate the head to face the direction movement (target.position - transform.position). Then the rest does the same except that the target is not defined by the input but by the previous position of the previous node.
thanks :), my only concern is that screen is consistently moving as it plays like your average runner. Will this still be possible?
Answer by tedthebug · Jun 09, 2015 at 06:32 AM
Here is a snippet covering movement that I used for a variant. I found that the kids couldn't relate to the snakes local direction so just made it so that the arrow keys represented the direction the player wanted to move on the screen e.g. UP= up screen, LEFT = head across the left of the screen etc. I set the initial # of segments then increased/decreased the int value as needed. Due to the speed the segments destroyed/instantiated I had to set the minimum to be 2 so it appeared there was 1 onscreen. The moveTimer is just how long the segments are onscreen before they loop thru & destroy/instantiate, it is used as a buffer for the speed & may not be the best way but I'm still learning & it worked for what I wanted :)
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI;
public class Manager : MonoBehaviour { static public Manager instance;
// create list of body segments
public List<InstantiateBody>bodySegments = new List<InstantiateBody> ();
public GameObject bodyPrefab;
// # of body segments, 2 is the minimum as 1 destroys & instantiates to quick to be seen.
public int bodyNum = 5;
// speed of snake & timer between destroy/instaniate for movement
float speed = 2 ;
float moveTimer = 0.5f;
// direction of movement for instantiation, player starts moving up the screen
public static Vector3 direction;
// player start position
private GameObject startspot;
// set exit gameobject
public GameObject exit;
// Use this for initialization
void Start ()
{
instance = this;
// get position of starting place
startspot = GameObject.Find ("Start");
// set player initial direction
direction = Vector3.forward;
}
// Update is called once per frame
void Update ()
{
// set player move direction by arrow keys
if (Input.GetKey (KeyCode.UpArrow))
direction = Vector3.forward;
if (Input.GetKey (KeyCode.DownArrow))
direction = Vector3.back;
if (Input.GetKey (KeyCode.LeftArrow))
direction = Vector3.left;
if (Input.GetKey (KeyCode.RightArrow))
direction = Vector3.right;
//decrement timer of action to replicate speed.
moveTimer -= speed * Time.deltaTime;
if (moveTimer <= 0) {
// replicate movement along 90 degree paths by destroying the body segment & removing it from the list
// at the end of the snake & instantiating one at the beginning 1 unit in the direction of movement
// from the segment at the start of the snake. Insert this new piece into position 0 of the list.
//remove last body segment in the list which will be the end of the snake
if (InstantiateBody.bodySegments.Count >= bodyNum) {
Destroy (InstantiateBody.bodySegments [InstantiateBody.bodySegments.Count - 1].gameObject);
InstantiateBody.bodySegments.RemoveAt (InstantiateBody.bodySegments.Count - 1);
}
// instantiate the body segments. If it's a new game first piece is at the start position
if (InstantiateBody.bodySegments.Count == 0) {
Instantiate (bodyPrefab, startspot.transform.position, bodyPrefab.transform.rotation);
// keep adding segments to the front of the snake
} else if (InstantiateBody.bodySegments.Count < bodyNum)
Instantiate (bodyPrefab, InstantiateBody.bodySegments [0].transform.position + direction, InstantiateBody.bodySegments [0].transform.rotation);
//reset move timer
moveTimer = 0.5f;
}
// set isTrigger for other segments, not the head, to enable collision detection if the
// snake hits itself.
for (int i = 0; i<InstantiateBody.bodySegments.Count-1; i++) {
if (i != 0) {
InstantiateBody.bodySegments [i].GetComponent<Collider> ().isTrigger = true;
}
}
}
}
Your answer
Follow this Question
Related Questions
Making a bubble level (not a game but work tool) 1 Answer
Multiple Cars not working 1 Answer
Help with Snake like movement algorithm. 1 Answer
Distribute terrain in zones 3 Answers
Animate Character movement? 1 Answer