I have the below c# script which works in parallel with the animator system within Unity. The user presses the right and left arrow keys to move left and right. I want to put this onto device. To do that I tried to use the new unity4.6+ UI system using buttons at bottom of screen but couldn't get it to work. The best option i Think is to use tilt or swipe, preferably tilt. Can anyone look at that script and point me in the right direction as to were the tilt function code would be placed ? Help is much appreciated..
using UnityEngine;
using System.Collections;
// Require these components when using this script
[RequireComponent(typeof (Animator))]
[RequireComponent(typeof (CapsuleCollider))]
[RequireComponent(typeof (Rigidbody))]
public class PlayerControl_S : MonoBehaviour
{
[System.NonSerialized]
public float meshMoveSpeed = 4.0f;
[System.NonSerialized]
public float animSpeed = 1.5f; // a public setting for overall animator animation speed
private Animator anim; // a reference to the animator on the character
private AnimatorStateInfo currentBaseState; // a reference to the current state of the animator, used for base layer
private AnimatorStateInfo layer2CurrentState; // a reference to the current state of the animator, used for layer 2
static int reloadState = Animator.StringToHash("Layer2.Reload"); // and are used to check state for various actions to occur
static int switchWeaponState = Animator.StringToHash("Layer2.WeaponSwap");
void Start ()
{
// initialising reference variables
anim = GetComponent<Animator>();
if(anim.layerCount ==2)
anim.SetLayerWeight(1, 1);
}
/*void OnAnimatorMove() //Tells Unity that root motion is handled by the script
{
if(anim)
{
Vector3 newPosition = transform.position;
newPosition.z += anim.GetFloat("Speed")* meshMoveSpeed * Time.deltaTime;
newPosition.x += anim.GetFloat("Direction") * meshMoveSpeed * Time.deltaTime;
transform.position = newPosition;
}
} */
void OnAnimatorMove() //Tells Unity that root motion is handled by the script
{
if(anim)
{
Vector3 newPosition = transform.position;
newPosition.z += anim.GetFloat("Speed")* meshMoveSpeed * Time.deltaTime;
newPosition.x += anim.GetFloat("Direction") * meshMoveSpeed * Time.deltaTime;
transform.position = newPosition;
}
}
void FixedUpdate ()
{
float h = Input.GetAxis("Horizontal"); // setup h variable as our horizontal input axis
float v = Input.GetAxis("Vertical"); // setup v variables as our vertical input axis
anim.SetFloat("Speed", 1f); // set our animator's float parameter 'Speed' equal to the vertical input axis
anim.SetFloat("Direction", h); // set our animator's float parameter 'Direction' equal to the horizontal input axis
anim.speed = animSpeed; // set the speed of our animator to the public variable 'animSpeed'
//anim.SetLookAtWeight(lookWeight); // set the Look At Weight - amount to use look at IK vs using the head's animation
currentBaseState = anim.GetCurrentAnimatorStateInfo(0); // set our currentState variable to the current state of the Base Layer (0) of animation
//Controls the movement speed
if(v <= 0.0f)
{
meshMoveSpeed = 4;
}
else
{
meshMoveSpeed = 6;
}
if(anim.layerCount ==2)
{
layer2CurrentState = anim.GetCurrentAnimatorStateInfo(1); // set our layer2CurrentState variable to the current state of the second Layer (1) of animation
}
You would want to put tilt controls in Update. You should mostly be using Fixed Update for the build in physics system IE manipulating rigid bodies.
Right now your code is only looking for vertical axis changes for movement speed. You can look into setting what is handled by GetAxis in joystick settings.
Related
I've been recently working on a project using Unity Engine that involves a sort of Top-Down, 3rd person view, and I have been having trouble with the character movement.
I want to implement a way for the player to move throughout the map using either WASD movement, Click-to-Move movement, or Drag-to-Move movement, allowing them to use either of these freely and at any time, yet I have not yet found a way of doing this, since the methods end up cancelling each other out, leading the Player Character to awkward movement and to getting stuck in place.
Is there any way of achieving this? If so, any tips/suggestions would be greatly appreciated. Please keep in mind I am a complete beginner when it comes to both Unity and C#, so I might not grasp some core concepts yet.
I have attached my PlayerMovement C# code below.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(test))]
public class PlayerMovement : MonoBehaviour
{
private test _input;
//click2move
private NavMeshAgent agent;
//x
[SerializeField]
private bool RotateTowardMouse;
[SerializeField]
private float MovementSpeed;
[SerializeField]
private float RotationSpeed;
[SerializeField]
private Camera Camera;
void Start()
{
//c2m
agent = GetComponent<NavMeshAgent>();
//x
}
private void Awake()
{
_input = GetComponent<test>();
}
// Update is called once per frame
void Update()
{
var targetVector = new Vector3(_input.InputVector.x, 0, _input.InputVector.y);
var movementVector = MoveTowardTarget(targetVector);
agent.autoBraking = true;
if (!RotateTowardMouse)
{
RotateTowardMovementVector(movementVector);
}
if (RotateTowardMouse)
{
RotateFromMouseVector();
}
//c2m
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (Input.GetMouseButtonDown(0))
{
agent.SetDestination(hit.point);
}
}
else
{
if (agent.remainingDistance < 1)
{
agent.ResetPath();
}
}
}
private void RotateFromMouseVector()
{
Ray ray = Camera.ScreenPointToRay(_input.MousePosition);
if (Physics.Raycast(ray, out RaycastHit hitInfo, maxDistance: 300f))
{
var target = hitInfo.point;
target.y = transform.position.y;
transform.LookAt(target);
}
}
private Vector3 MoveTowardTarget(Vector3 targetVector)
{
var speed = MovementSpeed * Time.deltaTime;
// transform.Translate(targetVector * (MovementSpeed * Time.deltaTime)); Demonstrate why this doesn't work
//transform.Translate(targetVector * (MovementSpeed * Time.deltaTime), Camera.gameObject.transform);
targetVector = Quaternion.Euler(0, Camera.gameObject.transform.rotation.eulerAngles.y, 0) * targetVector;
var targetPosition = transform.position + targetVector * speed;
transform.position = targetPosition;
return targetVector;
}
private void RotateTowardMovementVector(Vector3 movementDirection)
{
if (movementDirection.magnitude == 0) { return; }
var rotation = Quaternion.LookRotation(movementDirection);
transform.rotation = Quaternion.RotateTowards(transform.rotation, rotation, RotationSpeed);
}
}
I would highly recommend that you use the Unity Input System. It can automate switching between input devices and decouple your code from any specific controls. It might be a bit overwhelming if you have limited experience with C#, but there is a vast library of tutorial videos and written guides you can rely on.
The PlayerInput component is what detects when different input devices are added or removed and switches to the first valid control scheme. When a user activates the inputs required to trigger something in your game, that is represented as an Action. A set of callbacks for that action are called depending on the states of the input: started, performed, and canceled. These are where you hook up your character controller to the input and run any extra logic necessary to turn an input into movement. The Input System also has a feature called interactions that will probably be useful, especially for drag-to-move controls.
Good luck! If you'd like me to explain something further or point you to a good tutorial, feel free to tag me in a comment.
First create a Capsule in the scene, drag the main camera to its object, hang the script under the Capsule object, WASD controls the movement direction, the space moves up along the Y axis, and the F moves down along the Y axis, thank you
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCam : MonoBehaviour
{
private Vector3 m_camRot;
private Transform m_camTransform;//Camera Transform
private Transform m_transform;//Camera parent object Transform
public float m_movSpeed=10;//Movement factor
public float m_rotateSpeed=1;//Rotation factor
private void Start()
{
m_camTransform = Camera.main.transform;
m_transform = GetComponent<Transform>();
}
private void Update()
{
Control();
}
void Control()
{
if (Input.GetMouseButton(0))
{
//Get the mouse movement distance
float rh = Input.GetAxis("Mouse X");
float rv = Input.GetAxis("Mouse Y");
// rotate the camera
m_camRot.x -= rv * m_rotateSpeed;
m_camRot.y += rh*m_rotateSpeed;
}
m_camTransform.eulerAngles = m_camRot;
// Make the main character face in the same direction as the camera
Vector3 camrot = m_camTransform.eulerAngles;
camrot.x = 0; camrot.z = 0;
m_transform.eulerAngles = camrot;
// Define 3 values to control movement
float xm = 0, ym = 0, zm = 0;
//Press W on the keyboard to move up
if (Input.GetKey(KeyCode.W))
{
zm += m_movSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.S))//Press keyboard S to move down
{
zm -= m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.A))//Press keyboard A to move left
{
xm -= m_movSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.D))//Press keyboard D to move right
{
xm += m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.Space) && m_transform.position.y <= 3)
{
ym+=m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.F) && m_transform.position.y >= 1)
{
ym -= m_movSpeed * Time.deltaTime;
}
m_transform.Translate(new Vector3(xm,ym,zm),Space.Self);
}
}
I want to do a Game like slither.io in Unity but it's hard to detect when the mouse stopped moving, I want the ball to not stop, instead it should move on, worked several hours on this problem but can't quite get it to work. I thought if I save where the last known position is I can keep the velocity but I don't know how to implement yet.
Thanks in advance!
This is my Source Code:
private float xMin, xMax, yMin, yMax;
[SerializeField] float constantSpeed = 100f;
[SerializeField] float padding = 5f;
private Rigidbody2D rb2D;
private Vector3 mousePosition;
private Vector2 direction;
private List<Vector3> ListPos = new List<Vector3>();
private Vector3 empty;
// Use this for initialization
void Start () {
empty = Vector3.zero;
SetUpMoveBoundaries();
rb2D = gameObject.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update () {
Move();
}
private void SetUpMoveBoundaries()
{
Camera gameCamera = Camera.main;
xMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).x + padding;
xMax = gameCamera.ViewportToWorldPoint(new Vector3(1, 0, 0)).x - padding;
yMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).y + padding;
yMax = gameCamera.ViewportToWorldPoint(new Vector3(0, 1, 0)).y - padding;
}
private void Move()
{
if (Input.mousePosition != empty)
{
mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
direction = (mousePosition - transform.position).normalized;
ListPos.Add(direction);
rb2D.velocity = new Vector2(direction.x * constantSpeed, direction.y * constantSpeed);
}
else
{
var last = ListPos.LastOrDefault();
rb2D.velocity = new Vector2(last.x * constantSpeed, last.y * constantSpeed);
}
}
Assuming you want it to trigger one of the two functions depending on whether the mouse has moved or not since last frame:
Vector2 lastMousePosition;
void WhenMouseIsMoving()
{
}
void WhenMouseIsntMoving()
{
}
void Update()
{
if (Input.mousePosition!=lastMousePosition)
{
lastMousePosition=Input.MousePosition;
WhenMouseIsMoving();
} else
WhenMouseIsntMoving();
}
You'll need to add one more bool variable to keep track of whether it has just started or stopped moving;
If you want to check for mouse movement without having to keep track of the mouse position in a variable, you can use the GetAxis function from Unity's Input class.
To do this you will have to make sure that mouse movement is hooked up to axes in Unity's input manager. It is normally there by default already, with 'Mouse X' and 'Mouse Y' mapped to the mouse delta for their respective axes.
For example:
// Is true when the mouse has moved
if (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0)
{
// Do something with mouse input
}
In your case, it looks like you could do something like this as your move function:
Vector2 direction = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
if (direction.magnitude != 0)
{
// ListPos.Add(direction);
rb2D.velocity = direction.normalized * constantSpeed;
}
As an unrelated note, your ListPos variable is growing in size potentially every frame without limit. If you need to keep track of previous positions for reasons other than your attempt at detecting mouse position changes, you should consider how much storage you will need and give it a fixed size replacing the oldest entries, or consider whether or not the values need to be independent or can be merged instead.
I have looked over the internet for a Camera Script like the one in ROBLOX. But i can't seem to find one. Can anyone help me with this?
Btw i'm using Unity 2017.3
Welcome to Stack Overflow.
I will try to help you out. Please keep in mind though:
Generally questions like this will receive negative feedback as the question isn't specific enough and you haven't provided any attempts or code for us to work with.
People sometimes see this as a "can you do my work for me" scenario.
You are new so I want to take a stab at helping you out regardless.
I hope this helps you and potentially others.
I've included code comments for clarity.
TO USE THIS YOU MUST
create a new script in unity (C#) and attach it to your 'Player' GameObject
edit the script, and paste the below code into the editor
save the script and return to the editor, new settings will appear for the script
modify the settings to your liking and DRAG in the camera to the "The Camera" field
[Edit]
Probably worth mentioning, I also added a pause function to unlock the cursor and return control to the mouse, this can be built upon or removed as needed.
The script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThirdPersonCamera : MonoBehaviour {
//define some constants
private const float LOW_LIMIT = 0.0f;
private const float HIGH_LIMIT = 85.0f;
//these will be available in the editor
public GameObject theCamera;
public float followDistance = 5.0f;
public float mouseSensitivityX = 4.0f;
public float mouseSensitivityY = 2.0f;
public float heightOffset = 0.5f;
//private variables are hidden in editor
private bool isPaused = false;
// Use this for initialization
void Start () {
//place the camera and set the forward vector to match player
theCamera.transform.forward = gameObject.transform.forward;
//hide the cursor and lock the cursor to center
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update () {
//if escape key (default) is pressed, pause the game (feel free to change this)
if (Input.GetButton("Cancel"))
{
//flip the isPaused state, hide/unhide the cursor, flip the lock state
isPaused = !isPaused;
Cursor.visible = !Cursor.visible;
Cursor.lockState = Cursor.lockState == CursorLockMode.Locked ?
CursorLockMode.None : CursorLockMode.Locked;
System.Threading.Thread.Sleep(200);
}
if(!isPaused)
{
//if we are not paused, get the mouse movement and adjust the camera
//position and rotation to reflect this movement around player
Vector2 cameraMovement = new Vector2(Input.GetAxis("Mouse X"),Input.GetAxis("Mouse Y"));
//first we place the camera at the position of the player + height offset
theCamera.transform.position = gameObject.transform.position + new Vector3(0,heightOffset,0);
//next we adjust the rotation based on the captured mouse movement
//we clamp the pitch (X angle) of the camera to avoid flipping
//we also adjust the values to account for mouse sensitivity settings
theCamera.transform.eulerAngles = new Vector3(
Mathf.Clamp(theCamera.transform.eulerAngles.x + cameraMovement.y * mouseSensitivityY, LOW_LIMIT, HIGH_LIMIT),
theCamera.transform.eulerAngles.y + cameraMovement.x * mouseSensitivityX, 0);
//then we move out to the desired follow distance
theCamera.transform.position -= theCamera.transform.forward * followDistance;
}
}
}
This may be inactive, but here is one that moves on right click:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCamera : MonoBehaviour
{
private const float LOW_LIMIT = 0.0f;
private const float HIGH_LIMIT = 85.0f;
public GameObject theCamera;
public float followDistance = 5.0f;
public float mouseSensitivityX = 4.0f;
public float mouseSensitivityY = 2.0f;
public float heightOffset = 0.5f;
void Start()
{
theCamera.transform.forward = gameObject.transform.forward;
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
}
void Update()
{
if (Input.GetMouseButton(1))
{
Vector2 cameraMovement = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
theCamera.transform.position = gameObject.transform.position + new Vector3(0, heightOffset, 0);
theCamera.transform.eulerAngles = new Vector3(
Mathf.Clamp(theCamera.transform.eulerAngles.x + cameraMovement.y * mouseSensitivityY, LOW_LIMIT, HIGH_LIMIT),
theCamera.transform.eulerAngles.y + cameraMovement.x * mouseSensitivityX, 0);
theCamera.transform.position -= theCamera.transform.forward * followDistance;
}
}
}
I would like to make a smooth jump towards the nearest cube. I already have a script to detect the closest cube. I want that the X-axis is locked, so only the Y-axis and the Z-axis change when jumping. I would like to use a Jump animation when jumping. I already tried to use Vector3MoveTowards, but that didn't really work well, maybe I didn't use it properly.
Detect nearest cube where the player should jump to (C#)
void Update()
{
FindClosestCube ();
GameObject closestCube = FindClosestCube ();
Debug.Log (closestCube);
}
GameObject FindClosestCube() {
GameObject[] gos;
gos = GameObject.FindGameObjectsWithTag("cube");
GameObject closest = null;
float distance = Mathf.Infinity;
float position = transform.position.z;
foreach (GameObject go in gos) {
float diff = go.transform.position.z - position;
float curDistance = diff;
if (curDistance < distance) {
closest = go;
distance = curDistance;
}
}
return closest;
}
The tricky part is that at some cubes you have to jump up (y+1), with some cubes you jump towards the same Y (y+0) and with some cubes you jump down (y-1).
How do I do this?
Image of how it looks like:
EDIT: I have this code right now:
----------------C#-----------------
Rigidbody rb;
public int clicks = 0;
Vector3 target;
public Animation jumpAnimation;
bool jump = false;
float cubeDiffY;
bool movePlayer;
public float smoothTime = 0.3f;
public float yVelocity = 0.0f;
void Start()
{
rb = GetComponent<Rigidbody> ();
}
void Update ()
{
FindClosestCube ();
GameObject closestCube = FindClosestCube ();
Debug.Log ("Closestcube = " + closestCube);
target = closestCube.transform.position + new Vector3 (0f, 0.7f, 0f);
cubeDiffY = target.y - transform.position.y;
movePlayer = true;
Debug.Log("Cube Difference Y-axis = " + Mathf.Round(cubeDiffY));
if (Input.GetMouseButtonDown (0))
{
clicks += 1;
jump = true;
jumpAnimation = gameObject.GetComponent<Animation>();
//jumpAnimation.Play ();
}
if (jump == true)
{
Jump ();
}
}
void Jump()
{
float newPosition = Mathf.SmoothDamp (transform.position.y, target.y, ref yVelocity, smoothTime);
transform.position = new Vector3 (0, newPosition, transform.position.z);
}
I calculated the difference in Y-axis between the cube where the player is standing on and the closestCube. But the Jump() doesn't work. How do I fix that?
Okay I set up a quick version of your game and got what you wanted to work, it is not exactly a quick solution, because what your doing doesn't have built in functionality for other than using animations.
Here is the character script that has all the code you need and commented thoroughly so it should explain itself.
using UnityEngine;
public class Character : MonoBehaviour
{
//the collider for the player
private new BoxCollider collider;
//the jump box collider on a empty game object that is a child to the player object
public BoxCollider JumpBox;
//the offset of the cube so it doesn't stop inside of it
public Vector3 cubeOffset;
//how high the jump will be
public float JumpHeight;
//how fast the jump will be
public float JumpSpeed;
//holds the change in position the jump will produce
private Vector3 jumpDelta;
//holds the destination cube the jump is attempting to hit
private Cube destinationCube;
//true if a jumping animation is currently playing
private bool jumping = false;
//used to swap the jump direction from up to down
private bool jumpDirection = true;
//used to hold the position of the jump so it knows when to stop
private float jumpPosition = 0;
// Use this for initialization
void Start()
{
collider = GetComponent<BoxCollider>();
}
// Update is called once per frame
void Update()
{
if(jumping)
{
//move straight towards the cube
transform.position = transform.position + (JumpSpeed * jumpDelta);
//move up and down to simulate a jump
//check the current move direction
if (jumpDirection)
{
//add to the jump position twice product of the JumpHeight the JumpSpeed so that it will
//rise and fall the same amount of time it takes to move to the destination
jumpPosition += JumpHeight * JumpSpeed * 2;
//if it has passed the jump height reverse the jump direction
if (jumpPosition >= JumpHeight)
jumpDirection = !jumpDirection;
transform.position += transform.up * JumpHeight * JumpSpeed * 2;
}
//the jump direction is going down
else
{
jumpPosition -= JumpHeight * JumpSpeed * 2;
transform.position -= transform.up * JumpHeight * JumpSpeed * 2;
}
//check if the character collider intersects witht he cubes collider
//if it has then stop jumping and set the final position as the destination position
if (collider.bounds.Intersects(destinationCube.BoxCollider.bounds))
{
jumping = false;
transform.position = destinationCube.transform.position + cubeOffset;
}
}
//detect a jump
if (Input.GetKeyDown(KeyCode.Space))
{
//detect all hits on the jump box
Collider[] hits = Physics.OverlapBox(JumpBox.center, JumpBox.size * 0.5f);
//get the closest collider with the right tag
Collider result = GetClosestColliderWithTag(hits, "Cube");
//if we have a result then begin the jumping animation
if(result != null)
{
//gets the destination cubes cube component(the custom class you have on your cubes)
destinationCube = result.gameObject.GetComponent<Cube>();
//calculate the jump delta
jumpDelta = (result.transform.position + cubeOffset) - transform.position;
//remove the left and right components so the jumping doesnt move to the left or right of the player
Vector3 component = Vector3.Project(jumpDelta, -transform.right);
jumpDelta -= component;
component = Vector3.Project(jumpDelta, transform.right);
jumpDelta -= component;
//setup the jump animation control fields to the initial values
jumpPosition = 0;
jumpDirection = true;
jumping = true;
}
}
}
private Collider GetClosestColliderWithTag(Collider[] colliders, string tag)
{
//just gets the closest collider
float distance = float.MaxValue;
int result = -1;
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].tag == tag)
{
float distanceTemp = Vector3.Distance(transform.position, colliders[i].transform.position);
if (distanceTemp < distance)
{
distance = distanceTemp;
result = i;
}
}
}
if (result != -1)
return colliders[result];
else return null;
}
}
And here is my cube script which has some things you will need to add
using UnityEngine;
public class Cube : MonoBehaviour {
//these arent important just fields I used to set up a quick version of your game
public GameObject StartPoint;
public GameObject EndPoint;
public float Speed;
private Vector3 directionVector;
private bool direction;
//YOU WILL NEED THIS!!
[HideInInspector]
public BoxCollider BoxCollider;
// Use this for initialization
void Start() {
//not important
directionVector = EndPoint.transform.position - StartPoint.transform.position;
directionVector.Normalize();
//DONT FORGET TO SET YOUR BOX COLLIDER
BoxCollider = GetComponent<BoxCollider>();
}
// Update is called once per frame
void Update()
{
float distance = 0;
if (direction)
{
distance = Vector3.Distance(EndPoint.transform.position, transform.position);
transform.position += directionVector * Speed;
if (distance < Vector3.Distance(EndPoint.transform.position, transform.position))
direction = !direction;
}
else
{
distance = Vector3.Distance(StartPoint.transform.position, transform.position);
transform.position -= directionVector * Speed;
if (distance < Vector3.Distance(StartPoint.transform.position, transform.position))
direction = !direction;
}
}
}
Previous Answer
I would say you need to calculate the perceived position of the object in the future.
Vector3 futurePos = cubePos + (cubeMoveDirection * cubeMoveSpeed);
Once you have the future position, even if it is not exact, you should aim your animation towards that position. To do this I would have the animation change a speed vector instead of an actual transforms position that way we can rotate this speed vector in any direction you want while keeping the orientation of the block. Otherwise you have to rotate the entire block to point towards the direction you want. If this is what you want then put your block under a empty gameobject, rotate the empty gameobject to point to where you want and do the speed calculations only.
Next your animation should have a net move vector which should be pre-calculated and scaled down or up to meet the distance to the future position. It will look something like this(note this is not tested)
//class fields
Vector3 AnimatedSpeed;
Vector3 AnimationDelta;
//basic calculation
//get the direction vector from the players current position to the future
block position
Vector3 dirVector = futurePos - transform.position;
//find the rotation from the current orientation to the direction vector
Quaternion rotation = Quaternion.FromToRotation(transform.forward, dirVector);
//calculate the distance from you to the cube and scale it with the magnitude of the AnimationDelta
float result = Vector3.Distance(transform.position, futurePos);
result = result / animationDelta.magnitude;
//finally rotate the forward vector by the rotation and multiply it by the
//animation speed and the result to get the step by step movement as
//the animation plays. NOTE: The animation should be based on forward direction
transform.position += (AnimationSpeed * rotation) * result * Time.deltaTime;
Hopefully this does it, like I said I haven't tested it at all so you may have to do some tweaking based on your particular case as this is essentially psuedo-code.
Good luck! I'm off to bed I'll check back when I wake up.
I'm using the standard camera2DFollow script that comes with Unity 5. But I have a problem with the position of the camera. I've rotated my main camera and it looks like this now.
You see that my player is on top of the screen instead of the middle.
This is the default script in C# for the people who don't have it.
using System;
using UnityEngine;
namespace UnityStandardAssets._2D
{
public class Camera2DFollow : MonoBehaviour
{
public Transform target;
public float damping = 1;
public float lookAheadFactor = 3;
public float lookAheadReturnSpeed = 0.5f;
public float lookAheadMoveThreshold = 0.1f;
private float m_OffsetZ;
private Vector3 m_LastTargetPosition;
private Vector3 m_CurrentVelocity;
private Vector3 m_LookAheadPos;
// Use this for initialization
private void Start()
{
m_LastTargetPosition = target.position;
m_OffsetZ = (transform.position - target.position).z;
transform.parent = null;
}
// Update is called once per frame
private void Update()
{
// only update lookahead pos if accelerating or changed direction
float xMoveDelta = (target.position - m_LastTargetPosition).x;
bool updateLookAheadTarget = Mathf.Abs(xMoveDelta) > lookAheadMoveThreshold;
if (updateLookAheadTarget)
{
m_LookAheadPos = lookAheadFactor*Vector3.right*Mathf.Sign(xMoveDelta);
}
else
{
m_LookAheadPos = Vector3.MoveTowards(m_LookAheadPos, Vector3.zero, Time.deltaTime*lookAheadReturnSpeed);
}
Vector3 aheadTargetPos = target.position + m_LookAheadPos + Vector3.forward*m_OffsetZ;
Vector3 newPos = Vector3.SmoothDamp(transform.position, aheadTargetPos, ref m_CurrentVelocity, damping);
transform.position = newPos;
m_LastTargetPosition = target.position;
}
}
}
I want to change the Y to a +3 of the current position. So if my camera is on Y 2 than put it on Y 5. (This makes it so the player is in the middle and not on the top).
Thanks for the help!
You can do this by adding 3 to the camera's position at the end of each frame but I recommend against it.
What I would do, is create an empty object, name it "PlayerCameraCenter" and make the player parent to this object; then place the camera center wherever you want relative to the player, like y = 3, and make the camera follow this object instead of the player.
This way you can easily change the position of the camera, through the editor without fiddling with code.