So I'm trying to make an FPS-type game and is it possible to have a GameObject locked on the Y-axis/not able to move up or down? The GameObject is a model of an AWP from Counter Strike, I am making it move around the plane with the WASD keys, and when I use the mouse to look up/down, the AWP goes diagonally to where I'm looking, and I don't want that. My game looks like this: Screenshot
Here's the code I have for the AWP if it helps:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class AWPscript : MonoBehaviour {
public float speed = 5f;
// public float sensitivityX = 15.0f;
// public float sensitivityY = 15.0f;
public Camera MainCamera;
public Camera scopeCamera;
public float lookSensitivity = 10f;
public float xRotation ;
public float yRotation ;
public float currentXRotation;
public float currentYRotation;
public float xRotationV;
public float yRotationV;
public GameObject Scopepng;
public float lookSmoothDamp = 0.1f;
public Image ScopePNG;
public AudioClip sound;
// Use this for initialization
void Start () {
speed = 7.5f;
}
// Update is called once per frame
void Update () {
if(Input.GetKey(KeyCode.W))
transform.Translate(Vector3.forward * Time.deltaTime*speed);
if (Input.GetKey(KeyCode.S))
transform.Translate(Vector3.back * Time.deltaTime * speed);
if (Input.GetKey(KeyCode.A))
transform.Translate(Vector3.left * Time.deltaTime * speed);
if (Input.GetKey(KeyCode.D))
transform.Translate(Vector3.right * Time.deltaTime * speed);
if (Input.GetKey(KeyCode.LeftControl))
speed = 15f;
lookAround();
scope();
}
void scope()
{
if (Input.GetMouseButton(1))
{
MainCamera.enabled = false;
scopeCamera.enabled = true;
ScopePNG.enabled = true;
}
else
{
MainCamera.enabled = true;
scopeCamera.enabled = false;
ScopePNG.enabled = false;
}
}
void lookAround()
{
xRotation -= Input.GetAxis("Mouse Y") * lookSensitivity;
yRotation += Input.GetAxis("Mouse X") * lookSensitivity;
transform.rotation = Quaternion.Euler(xRotation, yRotation, 0);
}
}
Here's probably the simplest solution:
void Update () {
if(Input.GetKey(KeyCode.W))
transform.Translate(Vector3.forward * Time.deltaTime*speed);
if (Input.GetKey(KeyCode.S))
transform.Translate(Vector3.back * Time.deltaTime * speed);
if (Input.GetKey(KeyCode.A))
transform.Translate(Vector3.left * Time.deltaTime * speed);
if (Input.GetKey(KeyCode.D))
transform.Translate(Vector3.right * Time.deltaTime * speed);
if (Input.GetKey(KeyCode.LeftControl))
speed = 15f;
LookAround();
Scope();
JoeFix();
}
public float fixedFloatingHeightMeters; // set to say 1.4 in the editor
private void JoeFix()
{
Vector3 p = transform.position;
p.y = fixedFloatingHeightMeters;
transform.position = p;
}
PS! you really MUST rename lookAround to LookAround and scope to Scope. It can affect things later
Here's kind of an advanced piece of information that may be more what you want. Please try this also!
Currently you have a vector that is the NOSE OF THE OBJECT pointing.
Say the thing is heading NORTH, ok?
So, transform.forward is pointing North BUT, IT IS POINTING "DOWN A BIT".
Although it is pointing north, if you saw it from the side that vector is pointing DOWN A BIT.
What you really want is that vector, but FLAT, NOT POINTING DOWN OR UP. Right?!
In fact here's the magic to do that:
Vector3 correctDirectionButPossiblyDownOrUp = transform.forward;
Vector3 correctDirectionButFlatNoDownOrUp;
correctDirectionButFlatNoDownOrUp
= Vector3.ProjectOnPlane(
correctDirectionButPossiblyDownOrUp,
Vector3.up );
correctDirectionButFlatNoDownOrUp.Normalize();
correctDirectionButFlatNoDownOrUp is now the "magic" vector you want.
But, don't forget Translate works in LOCAL SPACE. (the "object's" idea of the world.) You very much want to move it in world space, which is easy. Notice the last argument: https://docs.unity3d.com/ScriptReference/Transform.Translate.html
transform.Translate(
correctDirectionButFlatNoDownOrUp * Time.deltaTime*speed,
Space.World);
So that's it !
footnote Don't forget "Vector3.up" has absolutely no connection to "Vector3".
If you don't need the gravity then removing the RigidBody component will stop Unity applying gravity and it will hover.
Related
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraSc : MonoBehaviour
{
public float sens;
public Transform body;
public Transform head;
float xRot = 0;
void Start()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
void Update()
{
float x = Input.GetAxisRaw("Mouse X") * sens * Time.deltaTime;
float y = Input.GetAxisRaw("Mouse Y") * sens * Time.deltaTime;
xRot -= y;
xRot = Mathf.Clamp(xRot,-80f,80f);
transform.localRotation = Quaternion.Euler(xRot,0f,0f);
body.Rotate(Vector3.up, x);
transform.position = head.position;
//transform.rotation = head.rotation;
}
}
I have a body and I want my camera to follow my head. it follows of course but it vibrates, its like its not moving , its teleporting to head every second. I tried using FixedUpdate but it was worse. I tried Lerp too but lerp makes camera follow slow, when I move my mouse quick it takes a lot of time to follow.
If you don't need any acceleration or advanced movement for your camera, you can simply make your camera gameobject a child of your head gameobject in the scene hierarchy (or prefab). This will make your camera copy the position and rotation of the head gameobject without any coding.
If you wish to make it third person view, you can simply modify the child position which will always be local to the parent's one.
Hopefully this helps.
It's can be complex problem. Maybe one of these solutions can help.
Why you use Input.GetAxisRaw() - this function return value without smoothing filtering, try Input.GetAxis() as alternative.
"Vibration" effect can be if camera position updates later than your body position. Try setup position for you body object in LateUpdate().
Problem can be in rotation calculation, in your case euler angles will be enough. Try to use something like this:
public float sens = 100.0f;
public float minY = -45.0f;
public float maxY = 45.0f;
private float rotationY = 0.0f;
private float rotationX = 0.0f;
private void Update()
{
rotationX += Input.GetAxis("Mouse X") * sens * Time.deltaTime;
rotationY += Input.GetAxis("Mouse Y") * sens * Time.deltaTime;
rotationY = Mathf.Clamp(rotationY, minY, maxY);
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
}
I have only been able to rotate it in the x axis but I would also like to do it in the z with the movement of the mouse. Sorry for the mistakes is google translator.
[SerializeField] private float camRotationAmount = 0.2f;
public Quaternion newRotation;
newRotation *= Quaternion.Euler(Vector3.up * Input.GetAxis("Mouse X"));
transform.rotation = Quaternion.Lerp(transform.rotation, newRotation, Time.deltaTime * camSmoothness);
I would like to add Input.GetAxis ("Mouse Y") for Vector3.left without tilting the camera. it's for a rts game. Thanks
In general you will want to separate the Y and X rotation the following way:
rotate around Y in global space
rotate around X in local space.
Whether you do this purely by logic or using a parent-child hierarchy is up to you ... second is easier to understand in my opinion.
Using the Hierarchy
There you would simply have a hierarchy like e.g.
CameraAnchor
|--Camera
and have a script on the CameraAnchor like e.g.
public class CameraAnchorController : MonoBehaviour
{
public float cameraSmoothness = 5f;
private Quaternion targetGlobalRotation;
private Quaternion targetLocalRotation;
private Transform child;
private void Start()
{
child = transform.GetChild(0);
targetGlobalRotation = transform.rotation;
targetLocalRotation = transform.GetChild(0).localRotation;
}
private void Update()
{
targetGlobalRotation *= Quaternion.Euler(Vector3.up * Input.GetAxis("Mouse X"));
targetLocalRotation *= Quaternion.Euler(Vector3.right * -Input.GetAxis("Mouse Y"));
var lerpFactor = cameraSmoothness * Time.deltaTime;
transform.rotation = Quaternion.Lerp(transform.rotation, targetGlobalRotation, lerpFactor);
child.localRotation = Quaternion.Lerp(child.localRotation, targetLocalRotation, lerpFactor);
}
}
Using Quaternion math
As said you could do the same thing in one single object but I would still keep both rotations separated:
public class CameraController : MonoBehaviour
{
public float cameraSmoothness = 5f;
private Quaternion targetGlobalRotation;
private Quaternion targetLocalRotation = Quaternion.identity;
private void Start()
{
targetGlobalRotation = transform.rotation;
}
private void Update()
{
targetGlobalRotation *= Quaternion.Euler(Vector3.up * Input.GetAxis("Mouse X"));
targetLocalRotation *= Quaternion.Euler(Vector3.right * -Input.GetAxis("Mouse Y"));
transform.rotation = Quaternion.Lerp(transform.rotation, targetGlobalRotation * targetLocalRotation, cameraSmoothness * Time.deltaTime);
}
}
Now why does this work when we are still using Vector3.right now?
By doing targetGlobalRotation * targetLocalRotation we first rotate around the global Y axis and then apply the rotation on the X axis based on this already applied rotation -> it is now an additional local rotation!
I have a script that has the enemy move towards the player at the same speed, but I am trying to make the enemy slow down then accelerate when he is switching directions. The enemy currently just moves left and write towards the player's position.
Here is my code from the script that my boss is attached to in the update function:
Vector2 targetPosition = new Vector2 (player.transform.position.x, transform.position.y);
transform.position = Vector2.MoveTowards (transform.position, targetPosition, moveSpeed * Time.deltaTime);
I have also tried using Lerp and using the transform.position as the first parameter, but the boss goes slower when the player is closer, and faster when the player is faster away.
transform.position = Vector2.Lerp (transform.position, targetPosition, moveSpeed * Time.deltaTime);
Does anyone know how to make the enemy slow down, then gradually increase his speed as he change direction, then return to normal speed after he has finished changing directions
**EDIT: ** full script below
using UnityEngine;
public class Roll : StateMachineBehaviour
{
[SerializeField] private float moveSpeed = 2.4f;
[SerializeField] private float rotateSpeed = 100f;
[SerializeField] private float minRollTime = 6f;
[SerializeField] private float maxRollTime = 8f;
private float rollTimer = 0f;
[SerializeField] private float rightBoundary = 5f;
[SerializeField] private float leftBoundary = -5f;
private Transform playerTransform = null;
private BossHealth bossHealth = null;
private Transform bossTransform = null;
private Transform bodyTransform = null;
private Transform earsTransform = null;
private Vector2 targetPosition = Vector2.zero;
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
playerTransform = GameObject.FindWithTag("Player").transform;
bossHealth = animator.GetComponent<BossHealth>();
Boss01 boss = FindObjectOfType<Boss01>();
bossTransform = boss.bossTransform;
bodyTransform = boss.bodyTransform;
earsTransform = boss.earsTransform;
rollTimer = Random.Range (minRollTime, maxRollTime);
}
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
if (bossTransform.position.x >= leftBoundary && bossTransform.position.x <= rightBoundary)
{
targetPosition = new Vector2(playerTransform.position.x, bossTransform.position.y);
bossTransform.position = Vector2.MoveTowards(bossTransform.position, targetPosition, moveSpeed * Time.deltaTime);
if (playerTransform.position.x > 0)
bodyTransform.Rotate(0f, 0f, -rotateSpeed * Time.deltaTime);
else
bodyTransform.Rotate(0f, 0f, rotateSpeed * Time.deltaTime);
}
else if (bossTransform.position.x < leftBoundary)
{
if (playerTransform.position.x > bossTransform.position.x)
{
targetPosition = new Vector2(playerTransform.position.x, bossTransform.position.y);
bossTransform.position = Vector2.MoveTowards(bossTransform.position, targetPosition, moveSpeed * Time.deltaTime);
}
}
else
{
if (playerTransform.position.x < bossTransform.position.x)
{
targetPosition = new Vector2(playerTransform.position.x, bossTransform.position.y);
bossTransform.position = Vector2.MoveTowards(bossTransform.position, targetPosition, moveSpeed * Time.deltaTime);
}
}
if (rollTimer <= 0f)
animator.SetTrigger ("aim");
else
rollTimer -= Time.deltaTime;
if (bossHealth.CheckHealth())
animator.SetTrigger ("transition");
if (earsTransform.rotation != Quaternion.Euler (0f, 0f, 0f))
earsTransform.rotation = Quaternion.Slerp(earsTransform.rotation, Quaternion.Euler(0f, 0f, 0f), 1f * Time.deltaTime);
}
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
animator.ResetTrigger ("aim");
animator.ResetTrigger ("transition");
}
}
To achieve the position (meters/second) you multiply the speed * Time.deltatime, so you achieve the meters. To handle acceleration, you need to handle variable speed. Acceleration is m/s2, multiplied * Time.deltatime you will have the instant speed, and that speed * Time.deltaTime will give you the position.
Here some pseudocode (step and speed should be class varibles and this modifieed in the update. accel is the constant acceleration, that should be constans for the simplicity's sake, I guess that you need uniformingly accelerated movement):
speed += accel * Time.deltaTime; // instant speed
step = speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
With the sign of the accel + or - you will determine if the entities speed is increasing (accelerating) or decreasing (decelerating).
Hope that helps
Edit:
Full script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveTowards : MonoBehaviour
{
public Transform target;
private float step = 0f;
private float speed = 0f;
public float accel = 0f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
speed += accel * Time.deltaTime; // instant speed
step = speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
}
Screenshot of script attached in editor:
Attached the script to the game object you want to move, and attach the transform of the target in the public fielld. The choose your acceleration, positive to accelerate towards an negative to accelerate backwars, and there you got it.
If I move forward while looking up my player jumps or at least attempts to fly. If I press Space bar and do move forward while looking up my player jumps even higher. I honestly have no idea on whats's going on. My prediction is the forward. If I look up Forward is relative to where I'm looking.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class P_MOVEMENT : MonoBehaviour
{
private float ACCELERATION = 10.0f;
private float GRAVITY = -5.0f;
private float SPEED = 5.0f;
private float RUNNING_SPEED = 2.0f;
private float JUMP_IMPULSE = 2.5f;
private bool isRunning = false;
CharacterController P_CC;
Vector3 P_MOVE;
//Camera Moving Mouse
private float X_AXIS = 0.0f;
private float Y_AXIS = 0.0f;
private float CAMERA_SPEED = 2.0f;
// Start is called before the first frame update
void Start()
{
P_CC = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
if(P_CC.isGrounded)
{
// Player Movement
P_MOVE = transform.forward * Input.GetAxis("Vertical") + transform.right * Input.GetAxis("Horizontal");
// Special Cases Check
// Running
isRunning = ( Input.GetKey(KeyCode.LeftShift) ) ? true : false;
P_MOVE = (isRunning) ? P_MOVE * SPEED * RUNNING_SPEED : P_MOVE * SPEED;
// Jumping
if(Input.GetAxis("Jump") > 0)
{
P_MOVE += Vector3.up * JUMP_IMPULSE;
}
}
else
{
P_MOVE += Vector3.up * GRAVITY * Time.deltaTime;
}
// Player Camera Movement
X_AXIS += CAMERA_SPEED * Input.GetAxis("Mouse X");
Y_AXIS -= CAMERA_SPEED * Input.GetAxis("Mouse Y");
// Restrict 90 Degree Up and Down
Y_AXIS = Mathf.Clamp(Y_AXIS, -60f, 90f);
// Update Rotation
transform.eulerAngles = new Vector3(Y_AXIS, X_AXIS, 0.0f);
}
void FixedUpdate()
{
P_CC.Move(P_MOVE * Time.deltaTime);
}
}
You are probably right. Your transform.forward is about the local GameObject coordinates instead of the global ones.
You could try to update only transform.forward.x and transform.forward.z. So you will ignore transform.forward.y. This way the player should not move up.
Something like this:
P_MOVE = transfrom.forward.x * Input.GetAxis("Vertical") + transform.forward.z * Input.GetAxis("Vertical") + transform.right * Input.GetAxis("Horizontal");
Very new to mono develop and Unity 3d and seem to be having issues with this code. First off, the code IS working. It does what it's supposed to, however, it also does some funky stuff that it's not supposed to. You are able to look up, down, left and right as well as walk those directions, the bad part is though for some reason my character likes to nudge the direction of the mouse when standing still. What am I missing? More efficient/less buggy way of doing this?
public class PlayerControl : MonoBehaviour {
public float WALK_SPEED = 1.3f;
public float RUN_SPEED = 4.0f;
public float STRAFE_SPEED = 5.0f;
public float ROTATION_SPEED = 300.0f;
public float JUMP_FORCE = 250.0f;
void Start()
{
}
// Update is called once per frame
void Update ()
{
float movementSpeed = WALK_SPEED;
float strafeSpeed = STRAFE_SPEED;
float rotationSpeedx = ROTATION_SPEED;
float rotationSpeedy = ROTATION_SPEED;
if (Input.GetKey(KeyCode.LeftShift))
{
movementSpeed = RUN_SPEED;
}
movementSpeed = Input.GetAxis("Vertical") * movementSpeed * Time.deltaTime;
strafeSpeed = Input.GetAxis("Horizontal") * strafeSpeed * Time.deltaTime;
rotationSpeedx = Input.GetAxis("Mouse X") * rotationSpeedx * Time.deltaTime;
rotationSpeedy = Input.GetAxis("Mouse Y") * rotationSpeedy * Time.deltaTime;
Vector3 rotate = new Vector3 (-rotationSpeedy, rotationSpeedx, 0);
transform.Translate(Vector3.forward * movementSpeed);
transform.Translate(Vector3.right * strafeSpeed);
transform.Rotate(rotate);
if (Input.GetKeyDown(KeyCode.Space) &&
transform.position.y < 30)
{
rigidbody.AddForce(Vector3.up * JUMP_FORCE);
}
}
}
Try freezing rotation constraints on rigidbody component. This may stop the nudging.