Moving the camera in the direction it is facing - c#

I've followed a tutorial on how to make a first person camera rotate and move in a 3D world in XNA on the Microsoft website. But when I rotate the camera along it's Y axis, it doesn't move the direction it is rotated/facing, instead it moves as if it was facing the direction it was originally faced.
Here's my code:
static Vector3 avatarPosition = new Vector3(0, 0, 0);
static Vector3 cameraPosition = avatarPosition;
Vector3 cameraReference = new Vector3(10, 0, 0);
// Create a vector pointing the direction the camera is facing.
Matrix world = Matrix.CreateWorld(new Vector3(0, -1, 0), Vector3.Forward, Vector3.Up);
Matrix rotationMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(0));
int Rot = 0;
Vector3 worldVector = new Vector3(5,-2, 0);
Matrix view, proj;
Vector3 cameraLookat;
Update()
{
world = Matrix.CreateWorld(worldVector, Vector3.Forward, Vector3.Up);
if (IsKeyDown(Keys.W))
avatarPosition += new Vector3(0.2f, 0f, 0);
if (IsKeyDown(Keys.S))
avatarPosition += new Vector3(-0.2f, 0f, 0);
if (IsKeyDown(Keys.A))
avatarPosition += new Vector3(0f, 0f, -0.2f);
if (IsKeyDown(Keys.D))
avatarPosition += new Vector3(0f, 0f, 0.2f);
if (IsKeyDown(Keys.Left))
Rot += 1;
if (IsKeyDown(Keys.Right))
Rot += -1;
rotationMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(Rot));
// Create a vector pointing the direction the camera is facing.
Vector3 transformedReference = Vector3.Transform(cameraReference, rotationMatrix);
// Calculate the position the camera is looking at.
cameraLookat = transformedReference + cameraPosition;
// Set up the view matrix and projection matrix.
view = Matrix.CreateLookAt(cameraPosition, cameraLookat, new Vector3(0.0f, 1.0f, 0.0f));
proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), graphics.GraphicsDevice.Viewport.AspectRatio,
0.1f, 1000);
cameraPosition = avatarPosition;
}
Can someone please tell me why the camera does not travel the way it is rotated? Or can someone please just give me the damn code to make one?

I appears the problem you are experiencing is coming from this area of the code:
if (IsKeyDown(Keys.W))
avatarPosition += new Vector3(0.2f, 0f, 0);
if (IsKeyDown(Keys.S))
avatarPosition += new Vector3(-0.2f, 0f, 0);
if (IsKeyDown(Keys.A))
avatarPosition += new Vector3(0f, 0f, -0.2f);
if (IsKeyDown(Keys.D))
avatarPosition += new Vector3(0f, 0f, 0.2f);
Instead of translating the avatarPosition directly along the x or z axis, it should be using the direction you're pointing which appears to be your transformedReference variable.
For instance, to move forward the way the camera is facing:
if (IsKeyDown(Keys.W))
avatarPosition += transformedReference;
However, since the transformedReference variable appears to be normalized, it may not move the avatar the distance you'd hoped. In that case simply multiply it by some constant MOVEMENT_SPEED for something like such:
if (IsKeyDown(Keys.W))
avatarPosition += transformedReference * MOVEMENT_SPEED;

Related

How to Move the position of a GameObject independently to its rotation?

I am creating a 3d top-down game, I have got the controls working for the gameobject and then got the rotation of the gameobject pointing to the mouse
though as I assumed, the controls of direction (w being up, s being down, etc) are affected due to the rotation so if it is being rotated 180 degrees, w is moving it down.
var dir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
transform.Translate(dir * _speed * Time.deltaTime);
GameObjectPosition = Camera.main.WorldToScreenPoint(transform.position);
MousePosition = Input.mousePosition;
float ObjectToMouseX = GameObjectPosition.x - MousePosition.x;
float ObjectToMouseY = GameObjectPosition.y - MousePosition.y;
float GameOjectAngle = -90-(float)Mathf.Atan2(ObjectToMouseY, ObjectToMouseX)*(180/Mathf.PI);
Vector3 GameObjectRotation = new Vector3(0, GameOjectAngle, 0);
transform.eulerAngles = GameObjectRotation;
this is what my code is so far
I haven't even tried to attempt this problem more so because I dont really know where to start

Object in a rotate loop in Unity

I was making a function so that my object can turn around. So I made this function:
void Drehen(){
if(Input.GetAxis("Horizontal") > 0.1){
transform.Rotate(new Vector3(0f, 0f, 0f));
vorne = true;
}
if(Input.GetAxis("Horizontal") > -0.1){
transform.Rotate(new Vector3(0f, 180f, 0f));
vorne = false;
}
}
The function checks the input if the player goes forwards or backwards and rotates him in the direction via transform.Rotate(new Vector3(0f, 180f, 0f));
Now, every time I start the game I am able to go forward but as soon as I go backward it flips every side every frame.
Well that's pretty obvious.
Rotate rotates the object from the current rotation about the given amount so
transform.Rotate(0, 0, 0);
does absolutely nothing at all and in
transform.Rotate(0, 180, 0);
you rotate it by 180° every frame.
In the second condition you have > -0.1 which is the case all the time while you don't press the negative key.
It should probably rather be < 0.1f.
What you want is probably rather e.g.
var horizontal = Input.GetAxis("Horizontal");
if(horizontal > 0.1f)
{
// or localRotation depending on your needs
transform.rotation = Quaternion.identity;
vorne = true;
}
else if(horizontal < 0.1f)
{
transform.rotation = Quaternion.Euler(0f, 180f, 0f);
vorne = false;
}
Or actually as alternative you could also do
var horizontal = Input.GetAxis("Horizontal");
if(Mathf.Abs(horizontal) > 0.1f)
{
transform.forward = new Vector3(0, 0, horizontal);
}
Try using
transform.eulerAngles = new Vector3(0f, 180f, 0f);

Shooting with a shotgun 2D Top-down Shooter

I'm trying to make shooting with a shotgun, I have already made shooting with one bullet. Code:
Vector2 shootingDirection = new Vector2(joystick.Horizontal, joystick.Vertical);
shootingDirection.Normalize();
if (shootingDirection != new Vector2(0, 0))
{
if(isShotGun) ShotGunShoot(shootingDirection);
GameObject bullet = Instantiate(bulletPrefab, crossHair.transform.position, Quaternion.identity);
bullet.transform.Rotate(0.0f, 0.0f, Mathf.Atan2(shootingDirection.y, shootingDirection.x) * Mathf.Rad2Deg);
bullet.GetComponent<Rigidbody2D>().AddForce(shootingDirection * 10f, ForceMode2D.Impulse);
}
}
But I'm just trying to create two other bullets with a slight deviation from the main one, so that it looks like a fraction, but it does not work correctly. Code:
private void ShotGunShoot(Vector2 dir)
{
GameObject shotGun = Instantiate(bulletPrefab, crossHair.transform.position, Quaternion.identity);
shotGun.transform.Rotate(0.0f, 0.0f, Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg - 30f);
shotGun.GetComponent<Rigidbody2D>().AddForce((dir + new Vector2(-.3f, 0f)) * 10f, ForceMode2D.Impulse);
shotGun = Instantiate(bulletPrefab, crossHair.transform.position, Quaternion.identity);
shotGun.transform.Rotate(0.0f, 0.0f, Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg + 30f);
shotGun.GetComponent<Rigidbody2D>().AddForce((dir+ new Vector2(.3f, 0f)) * 10f, ForceMode2D.Impulse);
}
As it should be
Here it is now
Thanks for help!
For the rotation. You can simply set the direction (from your image I can see that your bullet has to fly towards its right vector) like e.g.
shotgun.transform.right = dir;
shotgun.transform.Rotate(0, 0, 30);
For the add force: This uses world space directions.
You always pass in the direction and add the additional offset in world space. So that additional offset goes always in X axis direction regardless in which direction you shoot.
Rather take the direction into account by using the local force Rigidbody.AddRelativeForce
shotGun.GetComponent<Rigidbody2D>().AddForceRelative((shotgun.transform.right + new Vector2(0f, 0.3f)).normalized * 10f, ForceMode2D.Impulse);
This now uses the bullets right direction and additionally uses an offset of 0.3 along its local Y axis.
Btw: If you give your prefab the correct type
public Rigidbody bulletPrefab;
you can skip the GetComponent<Rigidbody> calls.

Rotate player on z axis while walking

i'm currently in progress of a new game where my character has to move. While my character walks forward and i'm rotating it on the z axis, it just rotates instead of walking down the new z axis.
void Update()
{
{
if (Input.GetKeyDown(KeyCode.W))
{
anim.SetInteger("Condition", 1);
moveDir = new Vector3(0, 0, 1);
moveDir *= speed;
moveDir = transform.TransformDirection(moveDir);
}
if (Input.GetKeyUp(KeyCode.W))
{
anim.SetInteger("Condition", 0);
moveDir = new Vector3(0, 0, 0);
}
moveDir.y -= gravity * Time.deltaTime;
controller.Move(moveDir * Time.deltaTime);
}
rot += Input.GetAxisRaw("Horizontal") * rotSpeed * Time.deltaTime;
transform.eulerAngles = new Vector3(0, rot, 0);
}
}
I want to be able to walk forward while changing the z axis instead of walking then stop and then walk again.
You can't do that using a CharacterController because your call to controller.move() overwrites the rotation ... you need to write a custom move function.

Change movement according to camera direction

Good day. I'm working on a fps game, and I have a problem with camera, or with movement to be pricese... as it doesn't take camera position into accound when performs movement...
I tried to fix it in several different ways, but I guess I just don't understand the math needed :(
Anyway, here's the code:
static public void UpdateCharacterPositionAndCamera(float time)
{
//mouse look update
float rotationSpeed = 3f;
if (Input.mouseState != Input.mouseStatePrevious)
{
float xDifference = Input.mouseState.X - Display.gd.Viewport.Width / 2;
float yDifference = Input.mouseState.Y - Display.gd.Viewport.Height / 2;
yRotation -= rotationSpeed * xDifference * time;
xRotation -= rotationSpeed * yDifference * time;
Mouse.SetPosition(Display.gd.Viewport.Width / 2, Display.gd.Viewport.Height / 2);
}
//camera
Vector3 cameraPosition = playerPos;
Vector3 cameraReference = new Vector3(0f, 0f, -1f);
Matrix rotationMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(yRotation)) * Matrix.CreateRotationX(MathHelper.ToRadians(xRotation));
Vector3 transformedReference = Vector3.Transform(cameraReference, rotationMatrix);
Vector3 cameraLookat = cameraPosition + transformedReference;
viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookat, new Vector3(0.0f, 1.0f, 0.0f));
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Display.gd.Viewport.AspectRatio, 0.1f, 2500.0f);
//movement
float moveSpeed = 5.0f;
Vector3 moveVector = new Vector3(0, 0, 0);
if (Input.keyState.IsKeyDown(Keys.Up) || Input.keyState.IsKeyDown(Keys.W))
moveVector += new Vector3(0, 0, -1);
if (Input.keyState.IsKeyDown(Keys.Down) || Input.keyState.IsKeyDown(Keys.S))
moveVector += new Vector3(0, 0, 1);
if (Input.keyState.IsKeyDown(Keys.Right) || Input.keyState.IsKeyDown(Keys.D))
moveVector += new Vector3(1, 0, 0);
if (Input.keyState.IsKeyDown(Keys.Left) || Input.keyState.IsKeyDown(Keys.A))
moveVector += new Vector3(-1, 0, 0);
if (Input.keyState.IsKeyDown(Keys.Q))
moveVector += new Vector3(0, 1, 0);
if (Input.keyState.IsKeyDown(Keys.Z))
moveVector += new Vector3(0, -1, 0);
playerPos += moveVector * moveSpeed;
}
Can you tell me how to change the move vector so it takes camera direction into account...?
Multiply the move vector by the camera rotation matrix, or its inverse (I think it's the inverse). It's the same as the view matrix, but without the translation. If you want to fix the camera onto a plane, you need to zero out the respective component afterwards and perhaps normalize the new vector.
I'm not familiar with the XNA API, so I cannot tell you exactly which methods to use. You might be able to extract the rotation matrix from the view matrix, or you might need to look at the difference (lookAt-positios) from the origin.
aere's how I usually do it:
//movement
Matrix camWorld = Matrix.Invert(view);
Vector3 moveVector = Vector3.Zero;
...
if(...keys.Up... or ...keys.W...)
moveVector += camWorld.Forward;
if(... keys.right or ... keys.D...)
moveVector += camWorld.Right;
...
moveVector.Normalize();
PlayerPos += moveVector * moveSpeed;

Categories

Resources