It has a similar feeling, but this code keeps following the player.
private void FixedUpdate()
{
Vector3 playerPos = _player.transform.position;
Vector3 dirVec = playerPos - transform.position;
dirVec = dirVec.normalized;
transform.Translate(dirVec * 1f * Time.fixedDeltaTime,Space.World);
transform.Rotate(0, 0, -Time.fixedDeltaTime * speed);
}
How can I implement it only in the direction of the player and not follow it?
use transorfm.lookAt() for simple direction following:
void FixedUpdate()
{
transform.LookAt(_player.transform, Vector3.up);
}
For smooth following:
public float rotateTime = 1f; // must not be zero
private void FixedUpdate()
{
var dirVec = _player.transform.position - transform.position;
var lookRotation = Quaternion.LookRotation(dirVec);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.fixedDeltaTime/rotateTime);
}
Related
I have been searching all day and reading forums but I can't find a way that works. I'm making a top-down view horror game. When my player walks normally he can look around with the cursor in any direction, but when he wants to run he switches to "tank" controls and rotates toward the running direction. I need something like this.
My player movement script so far:
public float walkSpeed;
public float runSpeed;
public float turnSpeed;
private Rigidbody2D rb;
public Camera cam;
private Vector2 moveDirection;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
ProcessInput();
}
void FixedUpdate()
{
Move();
}
private void ProcessInput()
{
float moveX = Input.GetAxisRaw("Horizontal");
float moveY = Input.GetAxisRaw("Vertical");
moveDirection = new Vector2(moveX, moveY).normalized;
}
void Move()
{
if (Input.GetKey(KeyCode.LeftShift))
{
//Looking toward movement direction should be applied here
} else {
rb.velocity = new Vector2(moveDirection.x * walkSpeed, moveDirection.y * walkSpeed);
Vector3 mousePosition = cam.ScreenToWorldPoint(Input.mousePosition);
Vector2 direction = mousePosition - transform.position;
float angle = Vector2.SignedAngle(Vector2.right, direction) - 90f;
Vector3 targetRotation = new Vector3(0, 0, angle);
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(targetRotation), turnSpeed * Time.deltaTime);
}
}
Any help is greatly appreciated! Thanks in advance!
This problem can be solved by substituting moveDirection instead of the mouse look direction, here it is enough to define a hypothetical variable called direction to detect the correct direction in each of these conditions.
var direction = new Vector2();
var currentSpeed = walkSpeed;
if (Input.GetKey(KeyCode.LeftShift))
{
direction = moveDirection;
currentSpeed = runSpeed;
} else {
direction = cam.ScreenToWorldPoint(Input.mousePosition) - transform.position;
}
var angle = Vector2.SignedAngle(Vector2.right, direction) - 90f;
var targetRotation = new Vector3(0, 0, angle);
var lookTo = Quaternion.Euler(targetRotation);
rb.velocity = new Vector2(moveDirection.x, moveDirection.y) * runSpeed *Time.deltaTime;
transform.rotation = Quaternion.RotateTowards(transform.rotation, lookTo , turnSpeed * Time.deltaTime);
I want to fix the code
So the image doesn't spin when translating to the next point
I tried to fix it, but could not
Apologized to the mistakes of writing, I do not speak English
enter image description here
[SerializeField]
private Transform[] patrolPoints;
Transform currentPatrolPoint;
int currentPatrolIndex;
protected override void Start()
{
currentPatrolIndex = 0;
currentPatrolPoint = patrolPoints[currentPatrolIndex];
base.Start();
}
protected override void Update()
{
transform.Translate(Vector3.up * Time.deltaTime * MySpeed);
if (Vector3.Distance(transform.position,currentPatrolPoint.position)<0.1f)
{
if(currentPatrolIndex+1<patrolPoints.Length)
{
currentPatrolIndex++;
}
else
{
currentPatrolIndex = 0;
}
currentPatrolPoint = patrolPoints[currentPatrolIndex];
}
Vector3 patrolPointDirection = currentPatrolPoint.position - transform.position;
float angle = Mathf.Atan2(patrolPointDirection.y, patrolPointDirection.x) * Mathf.Rad2Deg - 90f;
Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.RotateTowards(transform.rotation, q,180f);
}
If you don't want it to rotate, remove this part, which is rotating the GameObject:
float angle = Mathf.Atan2(patrolPointDirection.y, patrolPointDirection.x) * Mathf.Rad2Deg - 90f;
Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.RotateTowards(transform.rotation, q,180f);
Also any variable that you are using just for the transform.rotation can be removed from your code.
There is my script Rigidbody controller -
public float Speed = 5f;
public float JumpHeight = 2f;
public float GroundDistance = 0.2f;
public float DashDistance = 5f;
public LayerMask Ground;
private Rigidbody _body;
private Vector3 _inputs = Vector3.zero;
private bool _isGrounded = true;
private Transform _groundChecker;
void Start()
{
_body = GetComponent<Rigidbody>();
_groundChecker = transform.GetChild(0);
}
void Update()
{
_isGrounded = Physics.CheckSphere(_groundChecker.position, GroundDistance, Ground, QueryTriggerInteraction.Ignore);
_inputs = Vector3.zero;
_inputs.x = Input.GetAxis("Horizontal");
_inputs.z = Input.GetAxis("Vertical");
if (_inputs != Vector3.zero)
transform.forward = _inputs;
if (Input.GetButtonDown("Jump") && _isGrounded)
{
_body.AddForce(Vector3.up * Mathf.Sqrt(JumpHeight * -2f * Physics.gravity.y), ForceMode.VelocityChange);
}
if (Input.GetButtonDown("Sprint"))
{
Vector3 dashVelocity = Vector3.Scale(transform.forward, DashDistance * new Vector3((Mathf.Log(1f / (Time.deltaTime * _body.drag + 1)) / -Time.deltaTime), 0, (Mathf.Log(1f / (Time.deltaTime * _body.drag + 1)) / -Time.deltaTime)));
_body.AddForce(dashVelocity, ForceMode.VelocityChange);
}
}
void FixedUpdate()
{
_body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
}
What the best way to make a turn on y in the direction of the camera ? That is,the player turns to the side where the mouse is turned? Is it in fixedUpdate or update?
This is the camera script:
public float Smoothness = 0.3F;
public Vector2 Sensitivity = new Vector2(4, 4);
public Vector2 LimitX = new Vector2(-70, 80);
private Vector2 NewCoord;
public Vector2 CurrentCoord;
private Vector2 vel;
public GameManager GameMangerS;
public Transform Target;
public float TransformSpeed;
public Animator CameraAnimator;
void Update()
{
NewCoord.x = Mathf.Clamp(NewCoord.x, LimitX.x, LimitX.y);
NewCoord.x -= Input.GetAxis("Mouse Y") * Sensitivity.x;
NewCoord.y += Input.GetAxis("Mouse X") * Sensitivity.y;
CurrentCoord.x = Mathf.SmoothDamp(CurrentCoord.x, NewCoord.x, ref vel.x, Smoothness / 2);
CurrentCoord.y = Mathf.SmoothDamp(CurrentCoord.y, NewCoord.y, ref vel.y, Smoothness / 2);
transform.rotation = Quaternion.Euler(CurrentCoord.x, CurrentCoord.y, 0);
}
And added this line to the controller script -
void FixedUpdate()
{
_body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
transform.rotation = Quaternion.Euler(0, MainCamera.CurrentCoord.y, 0);
}
When I'm standing the player normally rotates, but when I start to move, all rotations are reset and the player is not moving.
Update
Simple Rotation can be achieved using transform.Rotate().
Example:
this.transform.Rotate(Vector3.up, 30);
This example is gonna rotate the transform by 30° around the Vector that points upwards.
LookAtMouse:
To make your object turn towards the mouse, you need the ScreenToWorldSpace() method from your camera. In order to convert the ScreenCoordinates into your WorldCoordinates.
Example:
Please note:
You have to set the camera instance! If you don't add that, you'll get a NullReferenceException.
This Snippets shall only show the steps needed to achieve the behavior you wish.
You will have to find out yourself how to integrate that lines of code into your code to make it work. Consider what Programmer told you in the comment when integrating that.
Vector3 mousePosition = Input.mousePosition; //get the screenSpaceMousePosition
Vector3 worldPosition = this.camera.ScreenToWorldPoint(mousePosition); //convert it into worldSpacePosition
Vector3 calculatedDirection = worldPosition - transform.position; //calucate the looking direction
calculatedDirection.y = 0;
Quaternion rotation = Quaternion.LookRotation(calculatedDirection);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime);
The spaceship start moving from point A. The spaceship is facing the moving direction.
Now when i click one on the L key i want that the spaceship will rotate and will face to the original position it was start moving from. But even if the spaceship is now rotated by axis Z or Y or X to rotate it first to the regular rotation values and to face to the start moving position.
using UnityEngine;
using System.Collections;
public class Control : MonoBehaviour
{
public int rotationSpeed = 75;
public int movementspeed = 10;
public int thrust = 10;
private bool isPKeyDown = false;
private float acceleration = .0f;
private Vector3 previousPosition = Vector3.zero;
private Rigidbody _rigidbody;
private Vector3 originalPosition;
private Quaternion originalRotation;
// Use this for initialization
void Start()
{
originalPosition = transform.position;
originalRotation = transform.rotation;
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
// Update is called once per frame
void Update()
{
var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
transform.position += transform.forward * Time.deltaTime * movementspeed;
if (Input.GetKey(KeyCode.Z))
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
if (Input.GetKey("p"))
{
isPKeyDown = Input.GetKey("p");
float distance = Vector3.Distance(previousPosition, transform.position);
acceleration = distance / Mathf.Pow(Time.deltaTime, 2);
previousPosition = transform.position;
_rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
}
if (Input.GetKey("l"))
{
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0);
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
}
IEnumerator TurnShip(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
{
float lerpSpeed = 0;
while (lerpSpeed < 1)
{
ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
lerpSpeed += Time.deltaTime * smooth;
yield return null;
}
}
void OnGUI()
{
if (isPKeyDown)
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
}
This is where i click the L button but i tried some things but can't yet find how to do it.
The main goal is if i click once on L the spaceship should automatic rotate if needed and move back to the original position and then land on ground. L stand for landing that's the main goal.
Add a variable on top -
...
private Vector3 originalPosition;
private Quaternion originalRotation;
private bool landShip = false;
...
And use following code in update function -
if (Input.GetKey("l"))
{
landShip = true;
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
if(landShip){
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0.5f);
}
Once the spaceship lands, set the landShip value back to false.
I'm struggling with this for quit some time now. I have GameObject, being a sphere, which is my player on a 3d Terrain. I have a Camera which is always on a fixed distance from the player, follows it where it goes with below script:
public GameObject player;
private Vector3 offset;
// Use this for initialization
void Start () {
offset = transform.position - player.transform.position;
}
void LateUpdate () {
transform.position = player.transform.position + offset;
}
So far so good. However what I actually want is that the camera rotates with the player, so it always looks into the direction where the sphere is moving, but always stays behind the player at the same fixed distance, so that the player is always visible in the camera view.
There are a lot of scripts available, but the problem with the onces I've seen so far is that the camera indeed rotate with the player, but because the player actually is a rolling sphere the camera view is rolling and turning as well.
The best script I found so far is below, but this one has the same problem as the other onces, the camera rolls with the player.
public Transform target;
public float distance = 3.0f;
public float height = 3.0f;
public float damping = 5.0f;
public bool smoothRotation = true;
public bool followBehind = true;
public float rotationDamping = 10.0f;
void Update () {
Vector3 wantedPosition;
if(followBehind)
wantedPosition = target.TransformPoint(0, height, -distance);
else
wantedPosition = target.TransformPoint(0, height, distance);
transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * damping);
if (smoothRotation) {
Quaternion wantedRotation = Quaternion.LookRotation(target.position - transform.position, target.up);
//Quaternion ownRotation = Quaternion.RotateTowards;
transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else transform.LookAt (target, target.up);
}
Can anyone help me with this please?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour {
public GameObject player;
public float cameraDistance = 10.0f;
// Use this for initialization
void Start () {
}
void LateUpdate ()
{
transform.position = player.transform.position - player.transform.forward * cameraDistance;
transform.LookAt (player.transform.position);
transform.position = new Vector3 (transform.position.x, transform.position.y + 5, transform.position.z);
}
}
My solution (based on #brennon-provencher answer) with smoothness and auto offset:
public class CameraFollow : MonoBehaviour
{
public GameObject target;
public float speed = 5;
Vector3 offset;
void Start()
{
offset = target.transform.position - transform.position;
}
void LateUpdate()
{
// Look
var newRotation = Quaternion.LookRotation(target.transform.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, speed * Time.deltaTime);
// Move
Vector3 newPosition = target.transform.position - target.transform.forward * offset.z - target.transform.up * offset.y;
transform.position = Vector3.Slerp(transform.position, newPosition, Time.deltaTime * speed);
}
}
You need to move your camera position based on sphere movement direction -
public GameObject player;
private Vector3 offset;
float distance;
Vector3 playerPrevPos, playerMoveDir;
// Use this for initialization
void Start () {
offset = transform.position - player.transform.position;
distance = offset.magnitude;
playerPrevPos = player.transform.position;
}
void LateUpdate () {
playerMoveDir = player.transform.position - playerPrevPos;
playerMoveDir.normalize();
transform.position = player.transform.position - playerMoveDir * distance;
transform.LookAt(player.transform.position);
playerPrevPos = player.transform.position;
}
Edit 2: To fix flickering camera, try this -
void LateUpdate () {
playerMoveDir = player.transform.position - playerPrevPos;
if (playerMoveDir != Vector3.zero)
{
playerMoveDir.normalize();
transform.position = player.transform.position - playerMoveDir * distance;
transform.position.y += 5f; // required height
transform.LookAt(player.transform.position);
playerPrevPos = player.transform.position;
}
}