I'm following a tutorial in C# and Unity and i have deviated a little off the code, I was hoping someone could help me understand how to add a MathF.Clamp to my code.
var delta = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")).normalized * Time.deltaTime * moveSpeed;
transform.position = new Vector3(
transform.position.x + delta.x,
transform.position.y + delta.y,
transform.position.z);
All advice is welcome. Thank you for your time.
Since you're using an orthographic camera, you can still use Mathf.Clamp and ViewportToWorldPoint. You'll just need to use it for each component. You can get the min and max for the x and y together by using ViewportToWorldPoint(new Vector3(0,0,0)); and ViewportToWorldPoint(new Vector3(1,1,0));.
Altogether, this might look like this:
private Camera mainCam;
Start()
{
// Camera.main calls FindGameObjectsWithTag internally, which is a costly operation.
// It's best to cache the results of Camera.main when possible to save on computation.
mainCam = Camera.main;
}
Update()
{
var delta = new Vector2(Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical")).normalized * Time.deltaTime * moveSpeed;
Vector3 minPos = mainCam.ViewportToWorldPoint(new Vector3(0,0,0));
Vector3 maxPos = mainCam.ViewportToWorldPoint(new Vector3(1,1,0));
transform.position = new Vector3(
Mathf.Clamp(transform.position.x + delta.x, minPos.x, maxPos.x),
Mathf.Clamp(transform.position.y + delta.y, minPos.y, maxPos.y),
transform.position.z);
}
This will keep your camera in bounds using Mathf.Clamp. You have to define the min and max values where the camera is allowed to move:
var delta = new Vector2(Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical")).normalized * Time.deltaTime * moveSpeed;
transform.position = new Vector3(
Mathf.Clamp(transform.position.x + delta.x, minX, maxX),
Mathf.Clamp(transform.position.y + delta.y, minY, maxX),
transform.position.z);
You can try something like this:
var delta = new Vector2(Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical")).normalized * Time.deltaTime * moveSpeed;
transform.position = new Vector3(
Mathf.Clamp(transform.position.x + delta.x, minX, maxX),
Mathf.Clamp(transform.position.y + delta.y, minY, maxX),
transform.position.z);
Related
Hi,
I've recently had a problem, I wanted to add the posibility to look on the sides with character camera in 3rd person, but it seems like after introducing it, the rest of the code seems to be ignored, like the beggining can be deleted and the rest is still working, although I think it shouldn't. It might be a bit messy, but does anyone know what's wrong?
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Camera : MonoBehaviour
{
public Transform ObjectToTrack;
public Vector3 delta;
void FixedUpdate()
{
transform.LookAt(ObjectToTrack);
var trackedRigidbody = ObjectToTrack.GetComponent<Rigidbody>();
var speed = trackedRigidbody.velocity.magnitude;
var targetPosition = ObjectToTrack.position + delta * (speed / 20f + 1f);
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.smoothDeltaTime * 3f);
}
float cameraAngle = 0f;
void Update()
{
if (Input.GetKey(KeyCode.Mouse0)) cameraAngle += Input.GetAxis("Mouse X");
var quaternionX = Quaternion.Euler(0, cameraAngle, 0);
var positionX = ObjectToTrack.position
+ quaternionX * delta;
transform.position = positionX;
transform.LookAt(ObjectToTrack);
transform.rotation *= Quaternion.Euler(-30f, 0, 0);
}
}
Update is called after fixed update(s) and so you're setting the position then overwriting it.
I would suggest changing this line
var positionX = ObjectToTrack.position + quaternionX * delta;
To
var positionX = transform.position + quaternionX * delta;
Or, more concisely just
transform.position += quaternionX * delta;
My objective here is to have a smoothed out "follow camera", for my space-fighter proof of concept game. The camera should match roll off the target object in all axis.
To that end I've "stolen" and modified this code from the unity Answers-site, and it works beautifully for X and Y (pitch and yaw), but it refuses to roll.
Code:
public float Distance;
public float Height;
public float RotationDamping;
public GameObject Target;
void LateUpdate()
{
var wantedRotationAngleYaw = Target.transform.eulerAngles.y;
var currentRotationAngleYaw = transform.eulerAngles.y;
var wantedRotationAnglePitch = Target.transform.eulerAngles.x;
var currentRotationAnglePitch = transform.eulerAngles.x;
var wantedRotationAngleRoll = Target.transform.eulerAngles.z;
var currentRotationAngleRoll = transform.eulerAngles.z;
currentRotationAngleYaw = Mathf.LerpAngle(currentRotationAngleYaw, wantedRotationAngleYaw, RotationDamping * Time.deltaTime);
currentRotationAnglePitch = Mathf.LerpAngle(currentRotationAnglePitch, wantedRotationAnglePitch, RotationDamping * Time.deltaTime);
currentRotationAngleRoll = Mathf.LerpAngle(currentRotationAngleRoll, wantedRotationAngleRoll, RotationDamping * Time.deltaTime);
var currentRotation = Quaternion.Euler(currentRotationAnglePitch, currentRotationAngleYaw, currentRotationAngleRoll);
transform.position = Target.transform.position;
transform.position -= currentRotation * Vector3.forward * Distance;
transform.LookAt(Target.transform);
transform.position += transform.up * Height;
}
Image:
I would be more certain about this answer if you explained what you were trying to do, but you should consider moving by Height in the direction of currentRotation * Vector3.up instead of transform.up. Also, consider using currentRotation * Vector3.up to set the local up direction when calling LookAt:
transform.position = Target.transform.position;
transform.position -= currentRotation * Vector3.forward * Distance;
Vector3 currentUp = currentRotation * Vector3.up;
transform.LookAt(Target.transform, currentUp);
transform.position += currentUp * Height;
I have a 3D game, where my camera is looking at all my terrain, and I have a character that moves with an Xbox controller. I want my character to only move in the direction that it is looking, not to the sides. I have the next code that makes my character move.
void Update()
{
MoveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = MoveInput * MoveSpeed;
Vector3 PlayerDirection = Vector3.right * -Input.GetAxisRaw("RHorizontal") + Vector3.forward * -Input.GetAxisRaw("RVertical");
if (PlayerDirection.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(PlayerDirection, Vector3.up);
}
The character moves with the left side of the controller, and with the right side, I can move the direction that is facing.
Currently, you're using the inputs as x and z components of a world space direction. It doesn't take into account the rotation of the character at all.
Instead, you should multiply the inputs and the corresponding local direction in world space, and then combine them. In your case, this might look like this:
MoveInput = (
transform.right * Input.GetAxisRaw("Horizontal")
+ transform.forward * Input.GetAxisRaw("Vertical")
).normalized;
moveVelocity = MoveInput * MoveSpeed;
Vector3 PlayerDirection = Vector3.right * -Input.GetAxisRaw("RHorizontal")
+ Vector3.forward * -Input.GetAxisRaw("RVertical");
if (PlayerDirection.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(PlayerDirection, Vector3.up);
}
The normalized is so you don't move faster diagonally.
I found a solution, here is the code:
MoveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = MoveInput * MoveSpeed;
Vector3 PlayerDirection = Vector3.right * Input.GetAxisRaw("Horizontal") + Vector3.forward * Input.GetAxisRaw("Vertical");
if (PlayerDirection.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(PlayerDirection, Vector3.up);
}
I want make an helicopter ai for game,
but i can't figure out how can i do flying movement.
I need 2 types of movement(Flying around and Flying to)
Helicopter will spawn at corner of map and fly to some player - FlyingTo
after Heli will arrive to a player it will start Flying around
and shoot missile.
I tried use transform.Translate, transform.rotation, rigidbody.force and many other things to movement, but didn't find anything working.
Few of my tries:
Vector3 flyto = (nearest.transform.position + new Vector3(0, 100, 0));
Vector3 Kouzlo1 = new Vector3(base.transform.position.x, 0, base.transform.position.z);
Vector3 Kouzlo2 = new Vector3(nearest.transform.position.x, 0, nearest.transform.position.z);
/*Vector3 targetDir = flyto - transform.position;
float step = 10 * Time.deltaTime;
Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, step, 0.0f);
transform.rotation = Quaternion.LookRotation(newDir);*/
if (Vector3.Distance(Kouzlo1, Kouzlo2) < 100)
{
var rotate = Quaternion.LookRotation(flyto - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotate,
Time.deltaTime * 10);
transform.Translate(Vector3.forward * 10 * Time.deltaTime);
/*transform.position = new Vector3(transform.position.x -
Vector3.Distance(Kouzlo1, Kouzlo2), nearest.transform.position.y + 100,
transform.position.z - Vector3.Distance(Kouzlo1, Kouzlo2));
Vector3 vvv = transform.rotation * new Vector3(0f, 1f, 0f);
transform.RotateAround(flyto, vvv, 180 * Time.deltaTime);*/
//transform.RotateAround(flyto, Vector3.forward, 10 * Time.deltaTime);
}else {
//transform.rotation = Quaternion.Slerp(transform.rotation,
Quaternion.LookRotation(flyto -transform.position), 10 * Time.deltaTime);
//transform.position += transform.forward * 10 * Time.deltaTime;
transform.LookAt(nearest.transform.position);
rigidbody.AddForce(Vector3.forward * 10);
}
You need to understand the method Lerp / Slerp first.
Lerp(a, b, t);
When t=0 it returns a, t=1 it returns b, otherwise it returns a value between a and b.
So you may use
Quaternion.Slerp(a, b, t += Time.deltaTime * 10);
And there is another similar method RotateTowards (or MoveTowards in Vector3 / Mathf class) can do same work
Quaternion.RotateTowards(a, b, Time.deltaTime);
For a few weeks, I've been trying to add strafing to my Player. I now have a working Script but when I try using the Mouse to Rotate the Player and the Camera the script is reacting wierd. When the Player is facing towards the Z-direction the Player is walking and running normaly, but as soon as I turn him around he slows down and moves super slow. Here's the code:
void Update () {
// input
Vector2 input = new Vector2 (Input.GetAxisRaw ("Horizontal"), Input.GetAxisRaw ("Vertical"));
Vector2 inputDir = input.normalized;
bool running = Input.GetKey (KeyCode.LeftShift);
if (!Input.GetMouseButtonDown(0) || Input.GetKey(KeyCode.JoystickButton2)) {
Move (inputDir, running);
Time.timeScale = 1;
}
if (Input.GetKeyDown (KeyCode.Space) || Input.GetKeyDown (KeyCode.JoystickButton0)) {
Jump ();
}
// animator
float animationSpeedPercent = ((running) ? currentSpeed.magnitude / runSpeed : currentSpeed.magnitude / walkSpeed * .5f);
void Move(Vector2 inputDir, bool running) {
float targetRotation = cameraT.eulerAngles.y;
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, GetModifiedSmoothTime(turnSmoothTime));
Vector2 targetSpeed = new Vector2(
((running) ? runSpeed : walkSpeed) * inputDir.normalized.x,
((running) ? runSpeed : walkSpeed) * inputDir.normalized.y);
currentSpeed = Vector2.SmoothDamp(currentSpeed, targetSpeed,
ref speedSmoothVelocity,
GetModifiedSmoothTime(speedSmoothTime));
velocityY += Time.deltaTime * gravity;
Vector3 velocity = (transform.forward * currentSpeed.y) +
(transform.right * currentSpeed.x) +
Vector3.up * velocityY;
controller.Move(velocity * Time.deltaTime);
currentSpeed = new Vector2(controller.velocity.x, controller.velocity.z);
if (controller.isGrounded)
{
velocityY = 0;
}
}
In order to allow a player to strafe in the default PlayerController, a couple edits must be made. I won't write the code for you, but here are the steps you need to take, they should be relatively easy to implement:
First, you need to comment out the code related to rotation
Then rather than obtaining the target speed as a scalar float, you should either calculate it as a Vector2 or as 2 separate floats (preferably the former)
Vector2 targetSpeed = new Vector2(
((running) ? runSpeed : walkSpeed) * inputDir.normalized.x,
((running) ? runSpeed : walkSpeed) * inputDir.normalized.y);
currentSpeed is a float, that relies on targetSpeed, but rather than~~ adjusting currentSpeed to also be a Vector2, you can use targetSpeed.magnitude when calculating the SmoothDamp
Since you need speed in both the Z context and the X context, you should make currentSpeed a Vector2 Thankfully there already exists a Vector2.SmoothDamp so that should be easy to refactor.
currentSpeed = Vector2.SmoothDamp(currentSpeed, targetSpeed,
ref speedSmoothVelocity,
GetModifiedSmoothTime(speedSmoothTime));
You need to include the X component in the velocity calculation. (remember that a Vector2's X and Y correspond to X and Z respectively on a Vector3)
Vector3 velocity = (transform.forward * currentSpeed.y) +
(transform.right * currentSpeed.x) +
Vector3.up * velocityY;
Finally, you want to adjust the currentSpeed to include the appropriate X, and Z velocities. This can be done simply by calculating the magnitude based on a Vector3 instead of a Vector2
currentSpeed = new Vector2(controller.velocity.x, controller.velocity.z);
By the way, welcome to StackOverflow - In the future you want to be sure to include a minimal, verifiable, and complete example, and not just the default unmodified code.
People are more willing to help if you've shown that you've made an effort yourself.