Rotate a GameObject to player position? - unity3d

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);
}

Related

I wrote a script for movement and mouse look, movement works but mouse look does not

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);
}
}
}

How to make my stick rotating after bouncing with button long pressed?

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;
}

Lerp to target position, but only within a radius

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);
}

How to make player to be able to rotate camera around cube in Unity?

I have created new Unity project, have added a cube into the center and now want to make player to be able to rotate camera around this cube by swipes and/or mouse drags.
Please, name simple steps to implement this or keywords to find an answer or where to read about it?
public Transform Target;
public float distance = 2.0f;
public float xSpeed = 20.0f;
public float ySpeed = 20.0f;
public float yMinLimit = -90f;
public float yMaxLimit = 90f;
public float distanceMin = 10f;
public float distanceMax = 10f;
public float smoothTime = 2f;
float rotationYAxis = 0.0f;
float rotationXAxis = 0.0f;
float velocityX = 0.0f;
float velocityY = 0.0f;
void Update()
{
if (Input.GetMouseButton(0))
{
velocityX += xSpeed * Input.GetAxis("Mouse X") * distance * 0.02f;
velocityY += ySpeed * Input.GetAxis("Mouse Y") * 0.02f;
}
rotationYAxis += velocityX;
rotationXAxis -= velocityY;
rotationXAxis = ClampAngle(rotationXAxis, yMinLimit, yMaxLimit);
Quaternion rotation = Quaternion.Euler(rotationXAxis, rotationYAxis, 0);
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + Target.position;
transform.rotation = rotation;
transform.position = position;
velocityX = Mathf.Lerp(velocityX, 0, Time.deltaTime * smoothTime);
velocityY = Mathf.Lerp(velocityY, 0, Time.deltaTime * smoothTime);
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
Taken from https://answers.unity.com/questions/1257281/how-to-rotate-camera-orbit-around-a-game-object-on.html
If you only want to rotate around a specific axis, for example around Y, you could basicly just do this
this.transform.RotateAround(Target.transform.position, Vector3.up, Input.GetAxis("Mouse X")*20.0f);
Create a new C# Script called "CameraRotate", open it and paste this script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraRotate : MonoBehaviour {
public Transform cube;
public float sensitivityX;
public float sensitivityY;
GameObject pivot;
void Start () {
pivot = new GameObject ("pivot");
pivot.transform.position = cube.position;
transform.SetParent (pivot.transform);
}
void Update () {
pivot.transform.eulerAngles += new Vector3 (Input.GetAxis ("Mouse Y") * -sensitivityX * Time.deltaTime, Input.GetAxis ("Mouse X") * sensitivityY * Time.deltaTime, 0);
}
}
Assign this script to your camera, then in Inspector Tab, with the camera selected, assign your Cube (drag) into the "cube" slot, and assign a value to the sensitivity fields (i used something about 500), press play and test.
What does this script do?
It creates a new GameObject at the center of the Cube to be a reference of rotation, it's called pivot. So it sets the Camera as a child of the pivot, and rotates the pivot according with your mouse axis.
I wrote this way:
float mouseX = -Input.GetAxis("Mouse X");
float mouseY = -Input.GetAxis("Mouse Y");
float magnitude = transform.position.magnitude;
Vector3 mouseSwipe = new Vector3(mouseX, mouseY, 0);
Vector3 startPoint = new Vector3((float)camera.pixelWidth / 2, (float)camera.pixelHeight / 2, magnitude - 1);
Vector3 startPointWorld = camera.ScreenToViewportPoint(startPoint);
Vector3 endPointWord = camera.ScreenToViewportPoint(startPoint + mouseSwipe);
Vector3 mouseSwipeWord = endPointWord - startPointWorld;
float dragLat = mouseSwipeWord.y;
float dragLng = mouseSwipeWord.x;
Vector3 oldPosition = transform.position / magnitude;
float lat = Mathf.Asin(oldPosition.y);
float rsmall = Mathf.Acos(oldPosition.y);
float lng = Mathf.Atan2(oldPosition.z / rsmall, oldPosition.x / rsmall);
lat += dragLat * 10 * 2 * Mathf.PI;
if( lat*180/Mathf.PI > 80 )
{
lat = 80 * Mathf.PI / 180;
}
else if( lat*180/Mathf.PI < -80)
{
lat = -80 * Mathf.PI / 180;
}
lng += dragLng * 10 * 2 * Mathf.PI * 2;
float y = Mathf.Sin(lat);
rsmall = Mathf.Cos(lat);
float x = rsmall * Mathf.Cos(lng);
float z = rsmall * Mathf.Sin(lng);
Vector3 newPosition = new Vector3(x, y, z);
newPosition *= magnitude;
transform.position = newPosition;
LookAtTarget();
The goal was to simulate mouse is rotation object by drag.

Unity 5: How to rotate an object in 3d space relative to camera axes

I'm trying to write a very simple 3d model viewer that allows the user to click and drag on the x and y axes to rotate an object. The problem I am facing with my included code sample is that, when I rotate something, say, about the y axis, and then try to rotate about the x axis, I find that the object is rotated about the object's x axis instead of the x-axis from the perspective of the camera.
I'm effectively trying to simulate rotating something along the z-axis, albeit through two motions.
public Transform obj;
private Vector3 screenPoint;
private Vector3 offset;
//public float minX = 270.0f;
//public float maxX = 360.0f;
//public float minY = -90.0f;
//public float maxY = 90.0f;
public float sensX = 100.0f;
public float sensY = 100.0f;
float rotationY = 0.0f;
float rotationX = 0.0f;
float posX = 0.0f;
float posY = 0.0f;
void Update() {
if (Input.GetMouseButton(0)) {
rotationX += Input.GetAxis("Mouse X") * sensX * Time.deltaTime;
//rotationX = Mathf.Clamp(rotationX, minX, maxX);
rotationY += Input.GetAxis("Mouse Y") * sensY * Time.deltaTime;
//rotationY = Mathf.Clamp(rotationY, minY, maxY);
Quaternion q = Quaternion.Euler(rotationY, -rotationX, 0);
transform.rotation = q;
}
if (Input.GetMouseButton(1)) {
posX += Input.GetAxis("Mouse X") * 25.0f * Time.deltaTime;
posY += Input.GetAxis("Mouse Y") * 25.0f * Time.deltaTime;
transform.position = new Vector3(posX, posY, 0);
}
}
If you are looking to rotate around the z-axis, you could try the transform.RotateAround function. This will allow you to specify a point (as a Vector3), a rotation axis (again as a Vector3), and a degree to which to rotate. This function can modify both the position and the rotation elements of your transform.