Rotation of player is slightly off - c#

I new to unity / c# and need some help with the rotation of my player. While I hold the mouse cursor on the positive y-axis (if the middle of the player is 0) the player faces slightly above the cursor and while on the negative y-axis the player faces slightly below the cursor. Here is a gif to demonstrate:
https://gyazo.com/e417962c20e186f3c6419c23bf8263f6
Here is my code for rotation.
public class LookTowardMouse : MonoBehaviour
{
void Update()
{
//Get the Screen positions of the object
Vector2 positionOnScreen = Camera.main.WorldToViewportPoint(transform.position);
//Get the Screen position of the mouse
Vector2 mouseOnScreen = (Vector2)Camera.main.ScreenToViewportPoint(Input.mousePosition);
//Get the angle between the points
float angle = AngleBetweenTwoPoints(positionOnScreen, mouseOnScreen);
//Rotate player
Debug.Log(angle);
transform.rotation = Quaternion.Euler(new Vector3(0f, 0f, angle));
}
float AngleBetweenTwoPoints(Vector3 a, Vector3 b)
{
return Mathf.Atan2(a.y - b.y, a.x - b.x) * Mathf.Rad2Deg;
}
}

Related

Unity 2D make item move around player in a cricle

So what I want is to move an item around the player in a circle but the item is moving along the circle depending on the mouse position. Im trying to do this as a sort of item equip thing and I can't get it to work.
What I have so far is the item moving in a circle around the player but not along the circle depending on the mouse position.
using UnityEngine;
public class Item : MonoBehaviour
{
public Transform target;
public SpriteRenderer renderer;
public float circleRadius = 1f;
public float rotationSpeed = 1f;
public float elevationOffset = 0f;
Vector2 positionOffset;
float angle;
void FixedUpdate()
{
positionOffset.Set(
Mathf.Cos(angle) * circleRadius,
Mathf.Sin(angle) * circleRadius
);
transform.position = new Vector3(target.position.x + positionOffset.x, target.position.y + positionOffset.y);
angle += Time.fixedDeltaTime * rotationSpeed;
}
}
If we assume that target is the "player" then we can:
Get the mouse position, as a world co-ordinate
Normalise the difference between the mouse and the player, times radius
Position the item along that normalised direction
private void Update ( )
{
var worldPosition = Camera.main.ScreenToWorldPoint( Input.mousePosition );
var positionOnCircle = (worldPosition - target.position).normalized * circleRadius;
transform.position = target.position + positionOnCircle;
}

How to limit/Clamp RotateAround for camera movement in Unity?

I have a scene with a globe, where the camera rotates around the globe. I need to clamp the position and rotation of this movement in certain instances of the game. I have tried several methods but none have worked. My code is below:
private void LateUpdate()
{
if (Input.GetMouseButtonDown(1))
mouseStartPosition = GetMouseHit();
if (mouseStartPosition != null)
DragPlanet();
if (Input.GetMouseButtonUp(1))
StaticPlanet();
}
public void RotateCamera(Vector3 dragStartPosition, Vector3 dragEndPosition)
{
//normalised for odd edges
dragEndPosition = dragEndPosition.normalized *planetRadius;
dragStartPosition = dragStartPosition.normalized * planetRadius;
// Cross Product
Vector3 cross = Vector3.Cross(dragEndPosition, dragStartPosition);
// Angle for rotation
float angle = Vector3.SignedAngle(dragEndPosition, dragStartPosition, cross);
//Causes Rotation of angle around the vector from Cross product
holderTransform.RotateAround(planet.transform.position, cross, angle);
}
private static Vector3? GetMouseHit()
{
RaycastHit hit;
int layer_mask = LayerMask.GetMask("Planet"); //raycasting on the planet
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, Mathf.Infinity, layer_mask))
{
return hit.point;

Monogame - Making the camera stop when my player collides

I have come to a position with my 3D game where I am now trying to perfect the camera. What I ultimately want is a working first person camera that stops when it collides with a wall. I assume you do this by having the camera move with a model and have the model collide to stop the camera also, i am just having issues seeing how to do that.
I have the model working so it stops, i just need to lock the camera from moving also. So far this is the code I have, making the model stop with collison:
if (player_health != 0)
{
if (kb.IsKeyDown(Keys.Left))
{
player_x = player_x + 0.05f;
world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
if (IsCollision(ball, world_player, ball, world_spike))
{
player_x = player_x - 0.05f;
world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
player_health = 0;
}
if (IsCollision(ball, world_player, ball, world_bullet[0]))
{
player_health = 0;
}
// use this code for any standard collision
if ((IsCollision(ball, world_player, ball, world_cannon)) || (IsCollision(ball, world_player, ball, walls[0])) || (IsCollision(ball, world_player, ball, walls[1])))
{
player_x = player_x - 0.05f;
world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
}
}
My camera added into the game1 class:
camera = new Camera(this, new Vector3(10f, 3f, 5f), Vector3.Zero, 5f);
Components.Add(camera);
And the camera class itself (I have been told this is rather over complicated? for a camera class, but the simpler ones didnt work):
namespace Game7
{
class Camera : GameComponent
{
private Vector3 cameraPosition;
private Vector3 cameraRotation;
private float cameraSpeed;
private Vector3 cameraLookAt;
private Vector3 mouseRotationBuffer;
private MouseState currentMouseState;
private MouseState previousMouseState;
// Properties
public Vector3 Position
{
get { return cameraPosition; }
set
{
cameraPosition = value;
UpdateLookAt();
}
}
public Vector3 Rotation
{
get { return cameraRotation; }
set
{
cameraRotation = value;
UpdateLookAt();
}
}
public Matrix Projection
{
get;
protected set;
}
public Matrix View
{
get
{
return Matrix.CreateLookAt(cameraPosition, cameraLookAt, Vector3.Up);
}
}
//Constructor
public Camera(Game game, Vector3 position, Vector3 rotation, float speed)
: base(game)
{
cameraSpeed = speed;
// projection matrix
Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.PiOver4,
Game.GraphicsDevice.Viewport.AspectRatio,
0.05f,
1000.0f);
// set camera positiona nd rotation
MoveTo(position, rotation);
previousMouseState = Mouse.GetState();
}
// set Camera's position and rotation
private void MoveTo(Vector3 pos, Vector3 rot)
{
Position = pos;
Rotation = rot;
}
//update the look at vector
private void UpdateLookAt()
{
// build rotation matrix
Matrix rotationMatrix = Matrix.CreateRotationX(cameraRotation.X) * Matrix.CreateRotationY(cameraRotation.Y);
// Look at ofset, change of look at
Vector3 lookAtOffset = Vector3.Transform(Vector3.UnitZ, rotationMatrix);
// update our cameras look at vector
cameraLookAt = cameraPosition + lookAtOffset;
}
// Simulated movement
private Vector3 PreviewMove(Vector3 amount)
{
// Create rotate matrix
Matrix rotate = Matrix.CreateRotationY(cameraRotation.Y);
// Create a movement vector
Vector3 movement = new Vector3(amount.X, amount.Y, amount.Z);
movement = Vector3.Transform(movement, rotate);
return cameraPosition + movement;
}
// Actually move the camera
private void Move(Vector3 scale)
{
MoveTo(PreviewMove(scale), Rotation);
}
// updat method
public override void Update(GameTime gameTime)
{
// smooth mouse?
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
currentMouseState = Mouse.GetState();
KeyboardState ks = Keyboard.GetState();
// input
Vector3 moveVector = Vector3.Zero;
if (ks.IsKeyDown(Keys.W))
moveVector.Z = 1;
if (ks.IsKeyDown(Keys.S))
moveVector.Z = -1;
if (ks.IsKeyDown(Keys.A))
moveVector.X = 1;
if (ks.IsKeyDown(Keys.D))
moveVector.X = -1;
if (moveVector != Vector3.Zero)
{
//normalize it
//so that we dont move faster diagonally
moveVector.Normalize();
// now smooth and speed
moveVector *= dt * cameraSpeed;
// move camera
Move(moveVector);
}
// Handle mouse input
float deltaX;
float deltaY;
if(currentMouseState != previousMouseState)
{
//Cache mouse location
deltaX = currentMouseState.X - (Game.GraphicsDevice.Viewport.Width / 2);
deltaY = currentMouseState.Y - (Game.GraphicsDevice.Viewport.Height / 2);
// smooth mouse ? rotation
mouseRotationBuffer.X -= 0.01f * deltaX * dt;
mouseRotationBuffer.Y -= 0.01f * deltaY * dt;
if (mouseRotationBuffer.Y < MathHelper.ToRadians(-75.0f))
mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(-75.0f));
if (mouseRotationBuffer.Y > MathHelper.ToRadians(75.0f))
mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(75.0f));
Rotation = new Vector3(-MathHelper.Clamp(mouseRotationBuffer.Y, MathHelper.ToRadians(-75.0f), MathHelper.ToRadians(75.0f)), MathHelper.WrapAngle(mouseRotationBuffer.X), 0);
deltaX = 0;
deltaY = 0;
}
// Alt + F4 to close now.
// Makes sure the mouse doesn't wander across the screen (might be a little buggy by showing the mouse)
Mouse.SetPosition(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
previousMouseState = currentMouseState;
base.Update(gameTime);
}
}
}
The Preview Move part of the camera class is meant to be where it detects for collision, at least the guide i followed said so, i just dont see how to integrate it. Thanks for any help or input, even if it is just a link to another guide or resource, would be very appreciated!
If your hero model (player) already has move functionality and collision functionality, and you want the camera to follow the model, then you can simplify the camera update tremendously.
Assuming after moving the player, the new position and/or orientation of the player is represented in player_world, simply borrow the location and orientation information stored in the player_world matrix to build a view matrix each frame.
//after moving player and setting its matrix accordingly:
view = Matrix.Invert(player_world);
And that is your complete camera class update. This creates a view matrix that is in the same position as the player and facing the same direction he is. If the player model stops because it hits a wall, then the camera (view matrix) stops too, because it is built from the player's 'stopped' matrix. No need to create a whole class for moving and rotating the camera around when the movement and rotation is the same as the player.
Sometimes the local player model origin would be located at the player's feet or belly and you want the camera up in the head where the eyes are. If so, simply apply something like this:
//after moving player and setting its matrix accordingly:
Matrix camera_world = player_world;
camera_world *= Matrix.CreateTranslation(Vector3.Up * ??f);// set ??f to the height difference between feet and head
view = Matrix.Invert(camera_world);

Rotate item: 90 degree rotations

I found this script that lets you click on an item then drag to rotate it, but it rotates based on where your finger is, what can I do to rotate the object 90 degrees like you would in Tetris?
public class RotateDrag : MonoBehaviour {
void OnMouseDrag(){
Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
pos = Input.mousePosition - pos;
float ang = Mathf.Atan2(pos.y, pos.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(ang, Vector3.forward);
}
}
Example
In photoshop when you want to rotate an item in a layer you can hold Shift and it will snap to 45° angles as you rotate.
I however would like 90° angle snapping.
What you need to do is just take the direction from the point selected, as the sign on the angle and apply that to a 90 degree rotation thus:
float ang = 90.0 * Math.Sign(Mathf.Atan2(pos.y, pos.x) * Mathf.Rad2Deg);
transform.rotation = Quaternion.AngleAxis(ang, Vector3.forward);

Rotate cameran around a gameobject in unity3d

I want to rotate camera around an fbx object when a key is being pressed using unity 3d.How it do? I tried some examples but its not working. First i create a game object and add main camera child of it.
public class CameraOrbit : MonoBehaviour
{
public Transform target;
public float speed = 1f;
private float distance;
private float currentAngle = 0;
void Start()
{
distance = (new Vector3(transform.position.x, 0, transform.position.z)).magnitude;
}
void Update()
{
currentAngle += Input.GetAxis("Horizontal") * speed * Time.deltaTime;
Quaternion q = Quaternion.Euler(0, currentAngle, 0);
Vector3 direction = q * Vector3.forward;
transform.position = target.position - direction * distance + new Vector3(0, transform.position.y, 0);
transform.LookAt(target.position);
}
}
I dont have access to unity at the moment so i might have messed something up.
The idea is keep an angle that you change based on input. Create a Quaternion from the angle (the Quaternion say how to rotate a vector to a certain direction), then rotate a Vector to that direction. Starting from the targets position move in that direction a certain distance and then look at the targets position.
This only implements rotation around the y axis, if you want rotation around the x axis all you need is another angle variable and then change to this Quaternion.Euler(currentAngleX, currentAngleY, 0);

Categories