I am making a 3D game but my player can only move on the X and Y axis. I have a player with an attached camera following my mouse, but I only want it to follow up to a max radius distance from Vector3.zero, even if my mouse is beyond those bounds.
I have tried repositioning the player to the max distance on radius every frame it tries to follow the mouse outside its bounds, but this causes camera jitters even in LateUpdate.
void LateUpdate()
{
if (Input.GetMouseButtonDown(0)) {
firstTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
playerPos = transform.position;
}
if (Input.GetMouseButton(0)) {
Ray currentTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
Vector2 direction = currentTouchPos.origin - firstTouchPos.origin;
float distance = Vector3.Distance(transform.position, Vector3.zero);
if (distance >= radius) {
targetPosition = direction.normalized * radius;
} else {
targetPosition = playerPos + direction * touchSensitivity;
}
}
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * followSpeed);
}
I'm thinking there must be a way to clamp the positioning of the player to a radius so that I don't have to "leash" him back by repositioning him through code every frame.
You should try using Vector3.ClampMagnitude().
The solution was to use Clamp Magnitude.
void LateUpdate()
{
if (Input.GetMouseButtonDown(0)) {
firstTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
playerPos = transform.position;
}
if (Input.GetMouseButton(0)) {
// targetPosition will follow finger movements
Ray currentTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
Vector2 direction = currentTouchPos.origin - firstTouchPos.origin;
targetPosition = playerPos + direction * touchSensitivity;
}
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * followSpeed);
transform.position = Vector3.ClampMagnitude(transform.position, radius);
}
Related
I am writing a script for movement and mouselook, the movement works but the mouse look does not. I start the game, the cursor locks into the game screen and I can move but I can't look around and there are no bugs. can someone help?
Here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_Controller : MonoBehaviour
{
[SerializeField]private float _speed = 7f;
[SerializeField]private float _mouseSensitivity = 50f;
[SerializeField]private float _minCameraview = -70f, _maxCameraview = 80f;
private CharacterController _charController;
private Camera _camera;
private float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
_charController = GetComponent<CharacterController>();
_camera = Camera.main;
if(_charController == null)
Debug.Log("No Character Controller Attached to Player");
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
//Get WASD Input for Player
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");
//move player based on WASD Input
Vector3 movement = Vector3.forward * vertical + Vector3.right * horizontal;
_charController.Move(movement * Time.deltaTime * _speed);
//Get Mouse position Input
float mouseX = Input.GetAxis("Mouse X") * _mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * _mouseSensitivity * Time.deltaTime;
//Rotate the camera based on the Y input of the mouse
xRotation -= mouseY;
//clamp the camera rotation between 80 and -70 degrees
xRotation = Mathf.Clamp(xRotation, _minCameraview, _maxCameraview);
_camera.transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
//Rotate the player based on the X input of the mouse
transform.Rotate(Vector3.up * mouseX * 3);
}
}
The problem is that you are multiplying the mouse input by Time.deltaTime. Time.deltaTime is used when you want to have different devices with different frame rates. This is because when multiplying by Time.deltaTime, you get a constant speed of one unit per second:
float speed = 10f;
float movement = speed * Time.deltaTime;
If you have a frame rate of 10fps (hopefully you don't), you would have each frame in 0.1 second. Each frame is 0.1 second, so when multiplying it by 10 (the speed), you get a value of one. If you speed the frame rate up, you would also get 10 units a second (1 x 10 = 10).
The mouse movement doesn’t need this because mouse movement is not handled by the computer. In other words, when you are moving the mouse, it isn’t changing by the frame rate, so you don’t need ‘Time.deltaTime`.
I also noticed that your movement was based on Vector3. What I mean by this is that you were using global coordinates rather than local (transform). This means if the play rotates, Vector3.forward will be different than the player’s forward. You should use transform.forward instead to use local coordinates.
You should change the script to this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_Controller : MonoBehaviour
{
[SerializeField]private float _speed = 7f;
[SerializeField]private float _mouseSensitivity = 50f;
[SerializeField]private float _minCameraview = -70f, _maxCameraview = 80f;
private CharacterController _charController;
private Camera _camera;
private float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
_charController = GetComponent<CharacterController>();
_camera = Camera.main;
if(_charController == null)
Debug.Log("No Character Controller Attached to Player");
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
//Get WASD Input for Player
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");
//move player based on WASD Input
Vector3 movement = transform.forward * vertical + transform.right * horizontal; //changed this line.
_charController.Move(movement * Time.deltaTime * _speed);
//Get Mouse position Input
float mouseX = Input.GetAxis("Mouse X") * _mouseSensitivity; //changed this line.
float mouseY = Input.GetAxis("Mouse Y") * _mouseSensitivity; //changed this line.
//Rotate the camera based on the Y input of the mouse
xRotation -= mouseY;
//clamp the camera rotation between 80 and -70 degrees
xRotation = Mathf.Clamp(xRotation, _minCameraview, _maxCameraview);
_camera.transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
//Rotate the player based on the X input of the mouse
transform.Rotate(Vector3.up * mouseX * 3);
}
}
This is a script for both movement and looking
[RequireComponent(typeof(CharacterController))]
public class NewBehaviourScript : MonoBehaviour
{
public float walkingSpeed = 7.5f;
public float runningSpeed = 11.5f;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
public Camera playerCamera;
public float lookSpeed = 2.0f;
public float lookXLimit = 45.0f;
CharacterController characterController;
Vector3 moveDirection = Vector3.zero;
float rotationX = 0;
[HideInInspector]
public bool canMove = true;
// Start is called before the first frame update
void Start()
{
characterController = GetComponent<CharacterController>();
// Lock cursor
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
// Update is called once per frame
void Update()
{
// We are grounded, so recalculate move direction based on axes
Vector3 forward = transform.TransformDirection(Vector3.forward);
Vector3 right = transform.TransformDirection(Vector3.right);
// Press Left Shift to run
bool isRunning = Input.GetKey(KeyCode.LeftShift);
float curSpeedX = canMove ? (isRunning ? runningSpeed : walkingSpeed) * Input.GetAxis("Vertical") : 0;
float curSpeedY = canMove ? (isRunning ? runningSpeed : walkingSpeed) * Input.GetAxis("Horizontal") : 0;
float movementDirectionY = moveDirection.y;
moveDirection = (forward * curSpeedX) + (right * curSpeedY);
if (Input.GetButton("Jump") && canMove && characterController.isGrounded)
{
moveDirection.y = jumpSpeed;
}
else
{
moveDirection.y = movementDirectionY;
}
// Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
// when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
// as an acceleration (ms^-2)
if (!characterController.isGrounded)
{
moveDirection.y -= gravity * Time.deltaTime;
}
// Move the controller
characterController.Move(moveDirection * Time.deltaTime);
// Player and Camera rotation
if (canMove)
{
rotationX += -Input.GetAxis("Mouse Y") * lookSpeed;
rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit);
playerCamera.transform.localRotation = Quaternion.Euler(rotationX, 0, 0);
transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeed, 0);
}
}
}
Code:
private Touch touch;
public float speed;
public Animator animator;
Vector3 point = new Vector3();
Vector3 targetPos;
void Start()
{
targetPos = transform.position;
}
void Update()
{
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved)
{
transform.position = new Vector3(transform.position.x + touch.deltaPosition.x * Time.deltaTime, transform.position.y, transform.position.z + touch.deltaPosition.y * Time.deltaTime);
Plane plane = new Plane(Vector3.up,transform.position);
Ray ray = Camera.main.ScreenPointToRay(touch.deltaPosition);
float point = 0f;
if (plane.Raycast(ray, out point)) targetPos = ray.GetPoint(point);
transform.LookAt(targetPos);
}
}
}
The problem is when I touch the screen the character looks in the touched direction, but when I move it forward (bottom of the screen to slightly above) it still looks towards the touch position. I want it so when it moves it faces the direction its going.
touch = Input.GetTouch(0);
if(touch.phase == TouchPhase.Moved)
{
transform.position = new Vector3(transform.position.x + touch.deltaPosition.x *
Time.deltaTime,transform.position.y,
transform.position.z + touch.deltaPosition.y * Time.deltaTime);
transform.LookAt(transform.position + touch.deltaPosition);
}
Basically I want to make bouncing stick and rotate control, with the left-right button.i'm facing an issue that the rotate not good as I expected because it won't follow my button like being affected by something after bouncing,
I'm using 2d physics material with friction = 1 and Bounciness = 0.9797 for perfect bouncing also attached to rigidbody2d.
I don't know, should I attach it on collider?
here my Player control Script:
public Rigidbody2D r2d;
public float vertical;
public float horizontal;
public Joystick joystick;
private void Start() {
r2d = gameObject.GetComponent < Rigidbody2D > ();
joystick = FindObjectOfType < Joystick > ();
}
private void Update() {
Movement();
}
public void Movement() {
r2d.velocity = r2d.velocity.normalized * 7f;
//horizontal = joystick.Horizontal;
//vertical = joystick.Vertical;
//if (horizontal == 0 && vertical == 0)
//{
// Vector3 curRot = transform.localEulerAngles;
// Vector3 homeRot = transform.localEulerAngles;
// transform.localEulerAngles = Vector3.Slerp(curRot, homeRot, Time.deltaTime * 2);
//}
//else
//{
// transform.localEulerAngles = new Vector3(0f, 0f, Mathf.Atan2(horizontal, vertical) * -180 / Mathf.PI);
//}
}
public Vector3 target;
public float rotationSpeed = 10f;
public float offset = 5;
public void turnLeft() {
Vector3 dir = target - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, angle + offset));
transform.rotation = Quaternion.Slerp(transform.rotation, -rotation, rotationSpeed * Time.deltaTime);
}
public void turnRight() {
Vector3 dir = target - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, angle + offset));
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, rotationSpeed * Time.deltaTime);
}
Whenever there is a Rigidbody/Rigidbody2D involved you do not want to manipulate anything via the .transform component!
This breaks the physics, collision detection and leads to strange movements basically the transform "fighting" against physics for priority.
What you rather want to do would be e.g. adjusting the Rigidbody2D.angularVelocity
public void turnLeft()
{
// Note that Time.deltaTime only makes sense if this is actually called every frame!
r2d.angularVelocity -= rotationSpeed * Time.deltaTime;
}
public void turnRight()
{
r2d.angularVelocity += rotationSpeed * Time.deltaTime;
}
I'm directly modifying an object position by moving it around with the mouse button.
Vector3 touchPosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
Vector3 touchPosition = new Vector3 (touchPosition.x, touchPosition.y, transform.position.z);
touchPosition.z = transform.position.z;
if(Input.GetMouseButton(0)) {
transform.position = newPosition;
}
What I want to find out is what is the average velocity of the object in the last few frames. Any idea how to do this?
Probably would look something like this:
Vector3 velocity;
Vector3 lastPosition = transform.position;
Vector3 touchPosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
Vector3 touchPosition = new Vector3 (touchPosition.x, touchPosition.y, transform.position.z);
touchPosition.z = transform.position.z;
if(Input.GetMouseButton(0)) {
transform.position = newPosition;
velocity = (newPosition - lastPosition) / Time.deltaTime;
}
I am creating a 2D game and I have a prefab enemy, this enemy is a cannon. I want rotate this cannon when player change position.
The cannon should always rotate to the player position
I'm trying this.
// Update is called once per frame
void Update () {
float distance = Vector2.Distance(player.position, transform.position);
if(distance < 10){
Vector2 dir = player.position - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion qto = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, qto, 5f * Time.deltaTime);
}
}
see the result: https://www.youtube.com/watch?v=REeSNKWLvIQ
The cannon isn't rotate to the player position.
How can I solve this problem ?
Your Code is Fine Just Make a Small Change And You Are Good to Go :
void Update () {
float distance = Vector2.Distance(player.position, transform.position);
if(distance < 10){
Vector2 dir = player.position - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion qto = Quaternion.AngleAxis(angle, Vector3.forward);
Quaternion qto2 = Quaternion.Euler (qto.eulerAngles.x,
qto.eulerAngles.y,
qto.eulerAngles.z + 90);
transform.rotation = Quaternion.Slerp(transform.rotation, qto2, 5f * Time.deltaTime);
}
}
I'm Just Add qto2 and Slerp to that.
You can try this code:
float turnspeed=1.0f;
//set a turning speed
void Update ()
{
dir = player.position - transform.position;
dir.Normalize();
transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(dir), turnSpeed *Time.deltaTime);
}