scrolling after camera rotation - c#

I am writing a kind of RTS CameraController in Unity using C#. I already managed to implement the basic functions, but now I am facing a tricky problem. I managed to rotate my camera and afterwards move into the right direction, BUT my scrolling boundaries are not working anymore after rotating (of course because I am just checking for x on the horizontal scrolling, but after rotation I would need to check for y instead). With boundaries I mean the restriction to only scroll until a certain position is reached (x < 0).
I am a bit stuck on how to solve my problem easily. One way would seems to be using conditions and check the rotation before checking for the boundaries, but this doesn't seem like a good aproach for me, just fixing the problem, but not really taking care of the cause. Now my question: Is there an easier or better way to achieve what I am doing? Did I miss something completely?
This is how I want the camera to move in all 4 rotations. The rectangles are my the world, the arrows define my bounds. The camera should always overshoot in backwards direction and stop before the bounds in forward direction.:
Here is my update method (vertDist and horDist are just defining from when on the mousescroll should start):
void LateUpdate() {
//LEFT
if((Input.mousePosition.x < horDist || Input.GetAxis("Horizontal") < 0)
&& transform.position.x > 0)
transform.Translate(-speed, 0, 0);
//RIGHT
if((Input.mousePosition.x > Screen.width - horDist || Input.GetAxis("Horizontal") > 0)
&& transform.position.x < world.worldX)
transform.Translate(speed, 0, 0);
//UP
if((Input.mousePosition.y > Screen.height - vertDist || Input.GetAxis("Vertical") > 0)
&& transform.position.z < world.worldZ - 30) {
Vector3 temp = transform.eulerAngles;
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, transform.eulerAngles.z);
transform.Translate(0, 0, speed);
transform.eulerAngles = temp;
}
//DOWN
if((Input.mousePosition.y < vertDist || Input.GetAxis("Vertical") < 0)
&& transform.position.z > -10) {
Vector3 temp = transform.eulerAngles;
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, transform.eulerAngles.z);
transform.Translate(0, 0, -speed);
transform.eulerAngles = temp;
}
//ZOOM
//camera.fieldOfView -= Input.GetAxis("Mouse ScrollWheel");
//ROTATE
if(Input.GetButtonDown("Rotate")){
Vector3 targetPosition = transform.position;
targetPosition += transform.forward * 27;
//transform.Rotate(new Vector3(0, Mathf.Sign(Input.GetAxis("Rotate")) * 90, 0), Space.World);
transform.RotateAround(targetPosition, Vector3.up, Mathf.Sign(Input.GetAxis("Rotate")) * 90);
}
}

Use
transform.Translate(0, 0, -speed, Space.Self); // For all the Translate, use Space.Self
It will only move based on it's local position instead of world position. But you will get what you wanted.
Hope it helps.

Finally I got a solution! I decided to define a Rect, depending on the current rotation and afterwards check if the camera-position is inside the Rect. Thus I had to mess a bit around with the positions, because I don't know why Rect.Contains() only takes the x- and y- coordinate of a position. My camera just moves along the x- and z-axis, so I did this weird coordinate swapping there:
void LateUpdate() {
Rect bounds = DefineBounds();
Vector3 pos = transform.position;
//LEFT
if((/*Input.mousePosition.x < horDist ||*/ Input.GetAxis("Horizontal") < 0)) {
pos += transform.TransformDirection(-speed * Time.deltaTime, 0, 0);
//reset pos if out of bounds
if(!bounds.Contains(new Vector2(pos.x, pos.z)))
pos -= transform.TransformDirection(-speed * Time.deltaTime, 0, 0);
}
//RIGHT
if((/*Input.mousePosition.x > Screen.width - horDist ||*/ Input.GetAxis("Horizontal") > 0)) {
pos += transform.TransformDirection(speed * Time.deltaTime, 0, 0);
//reset pos if out of bounds
if(!bounds.Contains(new Vector2(pos.x, pos.z)))
pos -= transform.TransformDirection(speed * Time.deltaTime, 0, 0);
}
//UP
if((/*Input.mousePosition.y > Screen.height - vertDist ||*/ Input.GetAxis("Vertical") > 0)) {
//Set camera x-angle to 0
Vector3 temp = transform.eulerAngles;
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, transform.eulerAngles.z);
pos += transform.TransformDirection(0, 0, speed * Time.deltaTime);
//reset pos if out of bounds
if(!bounds.Contains(new Vector2(pos.x, pos.z)))
pos -= transform.TransformDirection(0, 0, speed * Time.deltaTime);
//Reset camera x-angle
transform.eulerAngles = temp;
}
//DOWN
if((/*Input.mousePosition.y < vertDist ||*/ Input.GetAxis("Vertical") < 0)) {
//Set camera x-angle to 0
Vector3 temp = transform.eulerAngles;
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, transform.eulerAngles.z);
pos += transform.TransformDirection(0, 0, -speed * Time.deltaTime);
//reset pos if out of bounds
if(!bounds.Contains(new Vector2(pos.x, pos.z)))
pos -= transform.TransformDirection(0, 0, -speed * Time.deltaTime);
//Reset camera x-angle
transform.eulerAngles = temp;
}
transform.position = pos;
//ZOOM
//camera.fieldOfView -= Input.GetAxis("Mouse ScrollWheel");
transform.position = new Vector3(pos.x, pos.y - Input.GetAxis("Mouse ScrollWheel"), pos.z);
//ROTATE
if(Input.GetButtonDown("Rotate")){
Vector3 targetPosition = transform.position;
Vector2 posXZ;
targetPosition += transform.forward * 27;
transform.RotateAround(targetPosition, Vector3.up, Mathf.Sign(Input.GetAxis("Rotate")) * 90);
bounds = DefineBounds();
pos = transform.position;
posXZ = new Vector2(pos.x, pos.z);
while(!bounds.Contains(posXZ)) {
posXZ = Vector2.MoveTowards(posXZ, bounds.center, 1);
pos.x = posXZ.x;
pos.z = posXZ.y;
}
transform.position = pos;
}
}

Related

Unity align vehicle to road WITH rotation

Goal:
to create a vehicle with properties similar to that of Mario Kart 8's anti gravity mode, or f- zero; the ability to ride on extreme non horizontal surfaces.
Desired behavior:
the vehicle should not turn unless the thumbstick or arrow keys are pressed/moved; it must keep a straight line of motion with the exception of roll and vertical curvature relative to the camera's view.
Actual behavior:
The vehicle will slowly(sometimes quickly) fall out of line and keep curving until the track stops bending. if placed in an inward facing cylinder and driven around radially, the vehicle will begin to curve towards either global +z or global +y.
(no error messages)
What I've tried:
-setting transform.up to the surface normal then rotating around the normal as an axis
-using quaternion.euler(0, [desired angle], 0) then fromToRotation
The alignment and rotation code:
transform.rotation = Quaternion.Euler(0, rotation, 0);
Quaternion tilt = Quaternion.FromToRotation(Vector3.up, localUp);
transform.rotation = tilt * transform.rotation;
transform.position += velocity * 1.1f;
The entire script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using PhysicsExtensions;
using UnityEngine.Rendering.PostProcessing;
public class Cart : MonoBehaviour
{
Kartphysics inputActions;
public new Transform camera, camTarget, camTargetDrift, Visual;
public ShipType shipType;
public AudioSource Vroom;
public Vector3 localUp = Vector3.up;
Vector3 velocity, camUp, followPos;
public AnimationCurve SteeringControl;
public float steerAmount;
float rotation, rollTarget, roll, fovDifference, vroomPitch = 0, flameLength = 0;
public float normalFov, speedFov, Velocity, rollAmount, speedFactor, forcedAcceleration;
public GameObject[] ships;
public FlamingTrail[] flames;
public PostProcessProfile ppp;
Vector2 JoystickVal;
ChromaticAberration ca;
LensDistortion ld;
Vector3 LastForward;
private void Start()
{
switch (shipType)
{
case ShipType.Carrier:
{
ships[0].SetActive(true);
break;
}
case ShipType.Ram:
{
ships[1].SetActive(true);
break;
}
}
ca = ppp.GetSetting<ChromaticAberration>();
ld = ppp.GetSetting<LensDistortion>();
}
private void Update()
{
UpdateVisuals();
UpdateCamera();
Velocity = velocity.magnitude;
}
private void FixedUpdate()
{
UpdateKart();
}
void SetFlames(float length)
{
for(int i = 0; i < flames.Length; i++)
{
flames[i].length = length;
}
}
void UpdateVisuals()
{
ca.intensity.value = Mathf.Clamp01(forcedAcceleration) * 2;
ld.intensity.value = Mathf.Lerp(0, -70f, Mathf.Clamp(forcedAcceleration, 0, 1));
SetFlames(flameLength);
Vroom.pitch = Mathf.Lerp(Vroom.pitch, vroomPitch, (speedFactor * 0.01f) * 10);
Visual.position = Vector3.Lerp(Visual.position, transform.position, (speedFactor * 0.01f) * 30);
Visual.rotation = Quaternion.Lerp(Visual.rotation, transform.rotation, (speedFactor * 0.01f) * 15);
}
void UpdateCamera()
{
fovDifference = speedFov - normalFov;
Camera.main.fieldOfView = speedFov - (fovDifference * (1 / Mathf.Clamp(velocity.magnitude + 1, 0, Mathf.Infinity)));
camUp = Vector3.Lerp(camUp, localUp.normalized, (speedFactor * 0.01f) * (Vector3.Distance(camera.position, Vector3.Lerp(camTarget.position, camTargetDrift.position, transform.InverseTransformDirection(velocity).x)) + 3));
camera.rotation = Quaternion.Slerp(camera.rotation, Quaternion.LookRotation((transform.position - (transform.right * transform.InverseTransformDirection(velocity).x * 5) + transform.up) - camera.position, camUp), (speedFactor * 0.01f) * 13);
camera.position = Vector3.Lerp(camera.position, Vector3.Lerp(camTarget.position, camTargetDrift.position, transform.InverseTransformDirection(velocity).x), (speedFactor * 0.01f) * Vector3.Distance(camera.position, camTarget.position) * 20);
}
void UpdateKart()
{
JoystickVal = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
if (Input.GetAxis("Submit") > 0.5)
JoystickVal = new Vector2(JoystickVal.x, 1);
if (Input.GetAxis("Cancel") > 0.5)
JoystickVal = new Vector2(JoystickVal.x, -1);
if (JoystickVal.magnitude > 1)
{
JoystickVal.Normalize();
}
JoystickVal *= (speedFactor * 0.01f) * 0.2f;
JoystickVal /= Mathf.Clamp(velocity.magnitude, 0.7f, Mathf.Infinity);
velocity += ((transform.forward * JoystickVal.y) / Mathf.Clamp(Mathf.Abs(transform.InverseTransformDirection(velocity).x), 0.7f, Mathf.Infinity));
rollTarget = Mathf.Clamp01(SteeringControl.Evaluate(velocity.magnitude)) * JoystickVal.x * rollAmount;
roll = Mathf.MoveTowards(roll, rollTarget, (speedFactor * 0.01f) * 4);
velocity -= localUp * (speedFactor * 0.01f) * 0.7f;
velocity /= 1 + ((speedFactor * 0.01f) / 8);
RaycastHit hit;
CircleCastHit circleHit;
if (Physics.Raycast(transform.position + transform.up, -transform.up + (velocity / 1), out hit))
{
if (hit.distance < 4)
{
transform.position -= hit.normal.normalized * (speedFactor * 0.01f);
localUp = Vector3.MoveTowards(localUp, hit.normal, (speedFactor * 0.01f) * 9);
if (hit.distance < 1.2f)
{
flameLength = Velocity * 2;
if (hit.collider.tag == "SpeedPanel")
forcedAcceleration = 3f;
rotation += SteeringControl.Evaluate(velocity.magnitude * 0.7f) * JoystickVal.x * (speedFactor * 0.01f) * 100 * steerAmount;
transform.position += hit.normal.normalized * (1 - hit.distance);
vroomPitch = velocity.magnitude * 1.5f;
velocity += ((transform.forward * ((JoystickVal.y * 1.3f) + (forcedAcceleration / 100))) / Mathf.Clamp(Mathf.Abs(transform.InverseTransformDirection(velocity).x), 0.7f, Mathf.Infinity));
rotation += SteeringControl.Evaluate((speedFactor * 0.01f) * velocity.magnitude * 50) * JoystickVal.x * 0.3f;
velocity /= 1 + ((speedFactor * 0.01f));
velocity -= transform.right * transform.InverseTransformDirection(velocity).x * 0.2f;
Vector3 force = (hit.normal * -transform.InverseTransformDirection(velocity).y / Mathf.Clamp(hit.distance - 0.1f, 0.5f, 2)) * 1.1f;
if (force.magnitude > 1)
force = force.normalized * 1;
force /= 8;
velocity += force;
}
else
{
vroomPitch = 0;
flameLength = Mathf.MoveTowards(flameLength, 0, 0.03f);
}
}
else
{
localUp = Vector3.MoveTowards(localUp, Vector3.up, (speedFactor * 0.01f) * 1.2f);
vroomPitch = 0;
transform.forward = velocity.normalized;
flameLength = Mathf.MoveTowards(flameLength, 0, 0.03f);
}
}
else
{
localUp = Vector3.MoveTowards(localUp, Vector3.up, (speedFactor * 0.01f) * 2);
vroomPitch = 0;
flameLength = Mathf.MoveTowards(flameLength, 0, 0.03f);
}
if (PhysicsII.CircleCast(transform.position + (transform.up * 0.5f), localUp, 0.7f, 8, out circleHit))
{
Debug.DrawRay(circleHit.nearestHit().point, circleHit.nearestHit().normal, Color.red, 0.1f);
Debug.Log("HIT");
velocity += (transform.position + (transform.up * 0.5f) - circleHit.nearestHit().point) / 3;
if (circleHit.nearestHit().distance < 0.4f)
velocity += (transform.position + (transform.up * 0.5f) - circleHit.nearestHit().point) / 7;
if (circleHit.nearestHit().distance < 0.14f)
velocity += (transform.position + (transform.up * 0.5f) - circleHit.nearestHit().point) / 7;
}
if(Physics.Raycast(transform.position + (transform.up * 0.8f) - velocity, velocity , out hit))
{
if(hit.distance < Velocity * 2)
velocity /= 1 + ((speedFactor * 0.01f) * 2f);
if (hit.distance < Velocity * 1.2f)
velocity = Vector3.Reflect(velocity, hit.normal);
}
forcedAcceleration = Mathf.MoveTowards(forcedAcceleration, 0, 0.1f);
transform.rotation = Quaternion.Euler(0, rotation, 0);
Quaternion tilt = Quaternion.FromToRotation(Vector3.up, localUp);
transform.rotation = tilt * transform.rotation;
transform.position += velocity * 1.1f;
}
public enum ShipType
{
Carrier = 0,
Ram = 1
}
}
Here's a partial answer because I can't test it on my end currently to see if it works. It also appears like "roll" isn't yet used for anything (is it meant to alter the local up of the transform somehow?) so I'm not sure about that.
First, instead of keeping a float rotation to keep track of how the vehicle is turned, you can just use transform.forward or transform.right for those purposes, and measure the modifications to that on a per-frame basis:
void UpdateKart()
{
Vector3 newForward = transform.forward;
float turnAmount = 0f;
// ...
if (hit.distance < 1.2f)
{
flameLength = Velocity * 2;
if (hit.collider.tag == "SpeedPanel")
forcedAcceleration = 3f;
turnAmount += SteeringControl.Evaluate(velocity.magnitude * 0.7f)
* JoystickVal.x * (speedFactor * 0.01f) * 100 * steerAmount;
transform.position += hit.normal.normalized * (1 - hit.distance);
vroomPitch = velocity.magnitude * 1.5f;
velocity += /* too long to bother formatting */
turnAmount += SteeringControl.Evaluate((speedFactor * 0.01f)
* velocity.magnitude * 50) * JoystickVal.x * 0.3f;
// ...
Then when you actually adjust the rotation, apply the turn amount around the local up axis to the current local forward direction. And finally, set the transform's rotation so that its new local up is localUp and it keeps its local forward as constant a direction as possible (cross products followed by Quaternion.LookRotation can be used for this):
forcedAcceleration = Mathf.MoveTowards(forcedAcceleration, 0, 0.1f);
Vector3 turnedForward = Quaternion.AngleAxis(turnAmount - 180, localUp) *
transform.forward;
Vector3 newRight = Vector3.Cross(turnedForward, localUp);
if (newRight == Vector3.zero)
{
/* Ambiguous situation - maybe kart landed with its nose directly in the
direction of localUp or opposite direction. Possible solution: use
velocity as previous forward direction and recalculate, using a random
direction if that doesn't work
*/
newRight = Vector3.Cross(velocity, localUp);
if (newRight == Vector3.zero)
{
newRight = Vector3.ProjectOnPlane(Random.insideUnitSphere,
localUp).normalized;
}
}
Vector3 newForward = Vector3.Cross(newRight, localUp);
transform.rotation = Quaternion.LookRotation(newForward, localUp);
transform.position += velocity * 1.1f;
The reason you're seeing the results you are is that FromToRotation will give you the "smallest" rotation that will move one vector to the other. But you're more concerned with a rotation that will keep the local forward close to what they are before the adjustment (it's difficult to explain why this isn't the same thing). Hence the Cross stuff.
As I said, this is only intended to be a partial solution to get you closer. But, it may be all you need. Let me know what you think in the comments.

X axis rotation of a canvas ui joystick element doesnt work while Y axis does in Unity

Im trying to rotate a joystick that has an arrow image. The thing is that the joystick can rotate on the Y axis while it cant rotate on X. I couldn't figure out why this happens. Thanks.
if (Touch.TouchDist.x > 0)
{
Bow.transform.rotation = Quaternion.Lerp(Bow.transform.rotation, Quaternion.Euler(0f, 0f, -90f), 10f * Time.deltaTime);
}
if (Touch.TouchDist.x < 0)
{
Bow.transform.rotation = Quaternion.Lerp(Bow.transform.rotation, Quaternion.Euler(0f, 0f, 90f), 10f * Time.deltaTime);
}
if (Touch.TouchDist.y > 0)
{
Bow.transform.rotation = Quaternion.Lerp(Bow.transform.rotation, Quaternion.Euler(0f, 0f, -90f),10f* Time.deltaTime);
}
if (Touch.TouchDist.y < 0)
{
Bow.transform.rotation = Quaternion.Lerp(Bow.transform.rotation, Quaternion.Euler(0f, 0f, 90f),10f* Time.deltaTime);
}
If the "joystick can rotate on the Y axis while it cant rotate on X" it sounds like it's a malfunctioning :)
Jokes aside, it's not clear what your intentions are, but your code have some issues that can simply be improved and you may archieve what you are looking for if you change your code to this (be aware that the rotation will have acceleration):
if (Touch.TouchDist.x != 0)
{
Bow.transform.rotation = Quaternion.Lerp(Bow.transform.rotation, Quaternion.Euler(0f, 0f, 90f * Touch.TouchDist.x), 10f * Time.deltaTime);
}
if (Touch.TouchDist.y != 0)
{
Bow.transform.rotation = Quaternion.Lerp(Bow.transform.rotation, Quaternion.Euler(0f, 90f * Touch.TouchDist.y, 0f),10f* Time.deltaTime);
}
Further more, if you want to the gameobject to rotate at both directions at the same time, check this:
if (Touch.TouchDist.x != 0)
{
float y = Bow.transform.rotation.Euler.y;
Bow.transform.rotation = Quaternion.Lerp(Bow.transform.rotation, Quaternion.Euler(0f, y, 90f * Touch.TouchDist.x), 10f * Time.deltaTime);
}
if (Touch.TouchDist.y != 0)
{
float z = Bow.transform.rotation.Euler.z;
Bow.transform.rotation = Quaternion.Lerp(Bow.transform.rotation, Quaternion.Euler(0f, 90f * Touch.TouchDist.y, z),10f* Time.deltaTime);
}

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.

Unity3D Rotate ground using Acceleration is Shaking

I am trying to roll a ball using gravity. I am also trying to rotate the ground using the accelerometer but the ground is shaky when it rotates. I also can't set a limit on the rotation of the x Axis.
void Update()
{
tilt = new Vector3(Input.acceleration.x, Input.acceleration.y, Mathf.Clamp(Input.acceleration.z,-15,15));
tilt = Quaternion.Euler(90, 0, 90) * tilt; // Change Rotation according to camera view
if(tilt.x > 0.05f || tilt.x < -0.05f && tilt.x > -6f || tilt.x < 6f)
{
transform.localRotation = new Quaternion(-tilt.x, 0, 0, 3);
}
if (tilt.z < -0.1f || tilt.z >0.1f)
{
transform.localRotation = new Quaternion(0, 0, -tilt.z, 3);
}
}
See if this helps. This is a simple example of many ways to implement angular velocity.
Please be advised that Gimbel's lock effect is not considered in calculations. You might want to restrict the rotation in a certain range. Also you will need a dead zone for delta, e.g. if(delta < epsilon) delta = 0;.
float speed = 40f;
void Update()
{
tilt = new Vector3(Input.acceleration.x, Input.acceleration.y, Mathf.Clamp(Input.acceleration.z,-15,15));
tilt = Quaternion.Euler(90, 0, 90) * tilt; // Change Rotation according to camera view
if(tilt.x > 0.05f || tilt.x < -0.05f && tilt.x > -6f || tilt.x < 6f)
{
var delta = -tilt.x - transform.localRotation.x;
transform.localRotation += (new Quaternion(delta, 0, 0, 3) * Time.deltaTime * speed);
}
if (tilt.z < -0.1f || tilt.z >0.1f)
{
var delta = -tilt.z - transform.localRotation.z;
transform.localRotation += (new Quaternion(0, 0, -tilt.z, 3) * Time.deltaTime * speed);
}
}

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