I've been trying to figure this out for the past few hours and I figure there must be something off about my code making this extra difficult. I'm trying to make a first-person controller with the new input system and stop the camera from going 360 degrees vertically. I have the horizontal rotation applied to the player and the vertical rotation applied to a camera that is a child of said player. This is what I got sorry if it's a CF.
I've Tried Mathf.clamp and euler angles but I can't seem to get anything to work.
using UnityEngine;
using UnityEngine.InputSystem;
public class FirstPersonController : MonoBehaviour
{
public AICOde PlayerControls;
Vector2 moveDirection = Vector2.zero;
public Vector3 jumpForce;
float hlookDirection;
float vlookDirection;
public float isJumping;
public InputAction move;
public InputAction jump;
public InputAction look;
public Rigidbody rb;
public bool isOnGround;
public float moveSpeed;
public float sensitivity;
public Camera playerCamera;
public Quaternion cameraRotation;
private void Awake()
{
PlayerControls = new AICOde();
}
private void Start()
{
playerCamera = gameObject.GetComponentInChildren<Camera>();
Cursor.lockState = CursorLockMode.Locked;
}
private void OnEnable()
{
jump = PlayerControls.Player.Jump;
move = PlayerControls.Player.Move;
look = PlayerControls.Player.Look;
move.Enable();
jump.Enable();
look.Enable();
}
private void OnDisable()
{
move.Disable();
jump.Disable();
look.Disable();
}
private void Update()
{
cameraRotation = playerCamera.transform.rotation;
hlookDirection = look.ReadValue<Vector2>().x;
vlookDirection = look.ReadValue<Vector2>().y;
moveDirection = move.ReadValue<Vector2>();
isJumping = jump.ReadValue<float>();
}
private void FixedUpdate()
{
//MOVE PLAYER
rb.velocity = transform.TransformDirection (new Vector3(moveDirection.x * moveSpeed, rb.velocity.y, moveDirection.y * moveSpeed));
//ROTATE PLAYER WITH MOUSE
gameObject.transform.Rotate(Vector3.up, hlookDirection * sensitivity * Time.deltaTime );
//ROTATE CAMERA WITH MOUSE
playerCamera.transform.Rotate(Vector3.left,vlookDirection * sensitivity * Time.deltaTime);
//JUMP
if (isJumping > 0 && isOnGround == true)
{
rb.AddForce(jumpForce, ForceMode.Impulse);
}
if (isJumping > 0)
{
isOnGround = false;
}
if (isOnGround)
{
moveSpeed = 5f;
}
else
{
moveSpeed = 4f;
}
}
//MAKE SURE PLAYER IS ON GROUND BEFORE JUMPING
private void OnCollisionEnter(Collision collision)
{
if(collision.collider.CompareTag("Ground"))
{
isOnGround = true;
}
else
{
isOnGround = false;
}
}
}
You could track how much you have rotated up or down already. Define a float currentUpDownAngle = 0f; in your FirstPersonController. Then, instead of
//ROTATE CAMERA WITH MOUSE
playerCamera.transform.Rotate(Vector3.left,vlookDirection * sensitivity * Time.deltaTime);
you do
//ROTATE CAMERA WITH MOUSE
float MAX_UPDOWN_ANGLE = 60f; // define a limit (maybe somewhere else)
float change = vlookDirection * sensitivity * Time.deltaTime; // get the wanted change
// check if the change would exceed the maximum, we do it for both directions at once
// if you want another minimum angle, divide the code in two parts
if (Mathf.Abs(currentUpDownAngle + change) > MAX_UPDOWN_ANGLE) { // do we exceed?
float limit = Mathf.Sign(change) * MAX_UPDOWN_ANGLE; // get up or down limit
change = limit - currentUpDownAngle; // get the rest to limit
currentUpDownAngle = limit; // snap to the limit
}
else {
currentUpDownAngle += change; // no limit hit, free change
}
// rotates at most to the limit
playerCamera.transform.Rotate(Vector3.left, change);
Related
Camera rotate by mouse input, How to rotate the move to the default position?
public class CameraOrbit : MonoBehaviour
{
public float turnSpeed = 1.0f;
public Transform player;
private Vector3 offset;
private void Start()
{
offset = new Vector3(0, 2.5f, -5);
}
private void LateUpdate()
{
if (Input.GetMouseButton(0))
{
offset = Quaternion.AngleAxis(Input.GetAxis("Mouse X") * turnSpeed, Vector3.up) * offset;
transform.localPosition = offset;
transform.LookAt(player.position);
}
}
}
This kind of thing moves directly into position and I want to smooth it over.
public void RevertCamera()
{
offset = new Vector3(0, 2.5f, -5);
transform.localPosition = offset;
transform.LookAt(player.position);
}
I have tried multiple variations of this, but none of them seem to work.
the easiest way is to use the camera's transform's RotateAround(...) method:
void LateUpdate
{
if(Input.GetMouseDown(0))
{
float delta = Input.GetAxis("Mouse X") * turnSpeed;
transform.RotateAround(player.position, Vector3.up, delta);
}
}
(taken from: https://docs.unity3d.com/ScriptReference/Transform.RotateAround.html)
Suggestion: I usually set up a camera rig, if I want to control camera movement focused on a certain target.
Though this might be overengineered for a simple RotateAround call.
If you want to achieve smooth transitions. I would advise you to use Slerp on the Quaternion and interpolate between your 2 rotation points.
Slerp Example:
// Interpolates rotation between the rotations "from" and "to"
// (Choose from and to not to be the same as
// the object you attach this script to)
using UnityEngine;
using System.Collections;
public class SlerpExample: MonoBehaviour {
[SerializeField]private Transform from;
[SerializeField]private Transform player;
private bool revertCamera = false;
private float timeCount = 0.0f;
private void Update() {
timeCount = timeCount + Time.deltaTime;
if (revertCamera) {
timeCount = 0.0f;
transform.rotation = Quaternion
.Slerp(from.rotation, player.rotation, timeCount);
if (transform.rotation == player.rotation) {
reverCamera = false;
}
}
}
private void RevertCamera() {
revertCamera = true;
}
}
Slerp
I want to rotate camera around a gameObject (Say a cube) on a drag of my mouse to simulate a feeling that the gameObject is rotating (Just like we rotate object in scene editor and like in shopping websites).
The script below is the one that I'm using. But sometimes the script behaves very weirdly. The camera rotates in the opposite direction than the anticipated direction. Why is this happening? What changes do I need to make in the code to make it work? Please help.
using UnityEngine;
using System.Collections;
public class ExampleBehaviourScript : MonoBehaviour
{
public Camera cameraObj;
public GameObject myGameObj;
public float speed = 2f;
void Update()
{
RotateCamera();
}
void RotateCamera()
{
if(Input.GetMouseButton(0))
{
cameraObj.transform.RotateAround(myGameObj.transform.position,
Vector3.up,
-Input.GetAxis("Mouse X")*speed);
cameraObj.transform.RotateAround(myGameObj.transform.position,
Vector3.right,
-Input.GetAxis("Mouse Y")*speed);
}
}
}
I think it is caused by the reference axis.
Because you used Vector3.up, Vector3.right, not the camera's one, it wasn't rotated the anticipated direction.
So, you should change like below.
void RotateCamera()
{
if(Input.GetMouseButton(0))
{
cameraObj.transform.RotateAround(myGameObj.transform.position,
cameraObj.transform.up,
-Input.GetAxis("Mouse X")*speed);
cameraObj.transform.RotateAround(myGameObj.transform.position,
cameraObj.transform.right,
-Input.GetAxis("Mouse Y")*speed);
}
}
My solution to rotate the camera in Unity with Mouse or Touch
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class CameraRotator : MonoBehaviour
{
public Transform target;
public Camera mainCamera;
[Range(0.1f, 5f)]
[Tooltip("How sensitive the mouse drag to camera rotation")]
public float mouseRotateSpeed = 0.8f;
[Range(0.01f, 100)]
[Tooltip("How sensitive the touch drag to camera rotation")]
public float touchRotateSpeed = 17.5f;
[Tooltip("Smaller positive value means smoother rotation, 1 means no smooth apply")]
public float slerpValue = 0.25f;
public enum RotateMethod { Mouse, Touch };
[Tooltip("How do you like to rotate the camera")]
public RotateMethod rotateMethod = RotateMethod.Mouse;
private Vector2 swipeDirection; //swipe delta vector2
private Quaternion cameraRot; // store the quaternion after the slerp operation
private Touch touch;
private float distanceBetweenCameraAndTarget;
private float minXRotAngle = -80; //min angle around x axis
private float maxXRotAngle = 80; // max angle around x axis
//Mouse rotation related
private float rotX; // around x
private float rotY; // around y
private void Awake()
{
if (mainCamera == null)
{
mainCamera = Camera.main;
}
}
// Start is called before the first frame update
void Start()
{
distanceBetweenCameraAndTarget = Vector3.Distance(mainCamera.transform.position, target.position);
}
// Update is called once per frame
void Update()
{
if (rotateMethod == RotateMethod.Mouse)
{
if (Input.GetMouseButton(0))
{
rotX += -Input.GetAxis("Mouse Y") * mouseRotateSpeed; // around X
rotY += Input.GetAxis("Mouse X") * mouseRotateSpeed;
}
if (rotX < minXRotAngle)
{
rotX = minXRotAngle;
}
else if (rotX > maxXRotAngle)
{
rotX = maxXRotAngle;
}
}
else if (rotateMethod == RotateMethod.Touch)
{
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
//Debug.Log("Touch Began");
}
else if (touch.phase == TouchPhase.Moved)
{
swipeDirection += touch.deltaPosition * Time.deltaTime * touchRotateSpeed;
}
else if (touch.phase == TouchPhase.Ended)
{
//Debug.Log("Touch Ended");
}
}
if (swipeDirection.y < minXRotAngle)
{
swipeDirection.y = minXRotAngle;
}
else if (swipeDirection.y > maxXRotAngle)
{
swipeDirection.y = maxXRotAngle;
}
}
}
private void LateUpdate()
{
Vector3 dir = new Vector3(0, 0, -distanceBetweenCameraAndTarget); //assign value to the distance between the maincamera and the target
Quaternion newQ; // value equal to the delta change of our mouse or touch position
if (rotateMethod == RotateMethod.Mouse)
{
newQ = Quaternion.Euler(rotX , rotY, 0); //We are setting the rotation around X, Y, Z axis respectively
}
else
{
newQ = Quaternion.Euler(swipeDirection.y , -swipeDirection.x, 0);
}
cameraRot = Quaternion.Slerp(cameraRot, newQ, slerpValue); //let cameraRot value gradually reach newQ which corresponds to our touch
mainCamera.transform.position = target.position + cameraRot * dir;
mainCamera.transform.LookAt(target.position);
}
public void SetCamPos()
{
if(mainCamera == null)
{
mainCamera = Camera.main;
}
mainCamera.transform.position = new Vector3(0, 0, -distanceBetweenCameraAndTarget);
}
}
To move your cube in the direction of mouse moves change your code like blow:
void RotateCamera()
{
if (Input.GetMouseButton(0))
{
cameraObj.transform.RotateAround(myGameObj.transform.position,
Vector3.up,
Input.GetAxis("Mouse X") * speed);
cameraObj.transform.RotateAround(myGameObj.transform.position,
Vector3.right,
-Input.GetAxis("Mouse Y") * speed);
}
}
The grounded state for my character controller flickers on and off constantly at what seems to be every frame. From what I know, it's supposed to check if the player is grounded through player.isGrounded, but something else is moving it back up.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCharacterController: MonoBehaviour {
static Animator anim;
public bool walking;
public GameObject playerModel, Hero;
//Transforms
public Transform playerCam, character, centerPoint;
private Vector3 moveDirection;
//character controller declaration
CharacterController player;
//Mouse Rotation
private float rotX, rotY;
//Mouse Y Position
public float mouseYPosition = 1f;
//Mouse Sensitivity
public float Sensitivity = 10f;
//Mouse Zoom
private float zoom;
public float zoomSpeed = 2;
//Clamping Zoom
public float zoomMin = -2f;
public float zoomMax = -10f;
public float rotationSpeed = 5f;
//Move Front Back left & Right
private float moveFB, moveLR;
//Movement Speed
public float Speed = 2f;
//Velocity of Gravity
public float verticalVelocity;
//Jump Distance
public float jumpDist = 5f;
//Multiple Jumps
int jumpTimes;
//To use with Dialogue Manager
public DialogueManager DiagM;
public AudioClip jumpSound;
public AudioClip HurtSound;
public AudioClip PunchSound;
AudioSource audioSource;
//knockback
public float knockBackForce;
public float knockBackTime;
private float knockBackCounter;
// Use this for initialization
void Start ()
{
//character controller
player = GameObject.Find("Player").GetComponent<CharacterController> ();
StartCoroutine(MyCoroutine(character));
anim = GetComponent<Animator>();
//mouse zoom
zoom = -3;
centerPoint.transform.position = playerCam.transform.position;
centerPoint.transform.parent = null;
audioSource = GetComponent<AudioSource>();
}
IEnumerator MyCoroutine (Transform character)
{
if (player.isGrounded == true)
{
anim.SetBool("isFalling",false);
//anim.SetBool("isIdling", true);
yield return new WaitForSeconds(0);
}
}
// Update is called once per frame
void Update ()
{
//Mouse Zoom Input
zoom += Input.GetAxis ("Mouse ScrollWheel") * zoomSpeed;
if (zoom > zoomMin)
zoom = zoomMin;
if (zoom < zoomMax)
zoom = zoomMax;
//Mouse Camera Input
playerCam.transform.localPosition = new Vector3 (0, 0, zoom);
//Mouse Rotation
rotX += Input.GetAxis ("Mouse X") * Sensitivity;
rotY -= Input.GetAxis ("Mouse Y") * Sensitivity;
//Clamp Camera
rotY = Mathf.Clamp (rotY, -60f, 60f);
playerCam.LookAt (centerPoint);
centerPoint.localRotation = Quaternion.Euler (rotY, rotX, 0);
//Movement Speed
if (knockBackCounter <= 0)
{
moveDirection = (transform.forward * Input.GetAxis("Vertical")) + (transform.right * Input.GetAxis("Horizontal"));
moveDirection = moveDirection * Speed;
moveDirection.y = verticalVelocity;
player.Move(moveDirection * Time.deltaTime);
//Movement Rotation
centerPoint.position = new Vector3 (character.position.x, character.position.y + mouseYPosition, character.position.z);
//knockback disable
//Movement Input
if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0)
{
transform.rotation = Quaternion.Euler(0f, centerPoint.rotation.eulerAngles.y, 0f);
Quaternion turnAngle = Quaternion.LookRotation(new Vector3(moveDirection.x, 0f, moveDirection.z));
playerModel.transform.rotation = Quaternion.Slerp(playerModel.transform.rotation, turnAngle, Time.deltaTime * rotationSpeed);
if (player.isGrounded == true)
{
anim.SetBool("isWalking", true);
anim.Play("Running");
}
}
else
{
StartCoroutine(MyCoroutine(character));
}
if (Input.GetButtonDown("LHand"))
{
audioSource.PlayOneShot(PunchSound, 1F);
anim.Play("RPunch");
}
if (player.isGrounded == true)
{
jumpTimes = 0;
//verticalVelocity = -Physics.gravity.y * Time.deltaTime;
verticalVelocity = 0;
}
else
{
verticalVelocity += Physics.gravity.y * Time.deltaTime;
anim.SetBool("isWalking", false);
anim.SetBool("isFalling", true);
}
if (jumpTimes < 1)
{
if (Input.GetButtonDown("Jump"))
{
verticalVelocity += jumpDist;
anim.Play("Jump");
audioSource.PlayOneShot(jumpSound, 1F);
jumpTimes += 1;
}
}
}
else
{
knockBackCounter -= Time.deltaTime;
}
}
public void Knockback(Vector3 direction)
{
knockBackCounter = knockBackTime;
anim.Play("Jump");
audioSource.PlayOneShot(HurtSound, 50F);
moveDirection = direction * knockBackForce;
moveDirection.y = knockBackForce;
}
}
It looks like it has to do with the verticalVelocity lines, but so far I have only tried setting verticalVelocity = 0 and that works until I have actually moved the character. What could I change to stop the flickering?
Probably it is already solved, but the reason for that is that if you are using Character Controller you should apply gravity ALL the time to the character.
When the character collides with a object, it actually enters a little bit inside this object, then Unity pushes the character back away from the object, until it is no longer touching it. At this point, your gravity starts acting again, and re initiziling the cycle.
You need to apply gravity 100% of the time to create enough force to "balance" this fight with the floor. Could be a smaller "gravity" like 1. No need to be your gravity variable.
Also, on top of that, I like to add a "Coyote time", and make my on IsGrounded() method, as follows:
public bool IsGrounded()
{
return CoyoteTime < CoyoteTimeMax;
}
public void CoyoteControl()
{
if (CharController.isGrounded)
{
CoyoteTime = 0;
}
else
{
CoyoteTime += Time.deltaTime;
}
}
And then I call the CoyoteControl() on Update(), and I can call IsGrounded() whenever I need.
On the inspector I usually set the CoyoteTimeMax to 0.1 and it makes falls more smooth.
As per you comment. You should not determine if your player is grounded by checking an animation parameter. The best way is to use a RayCast(). So what you have to do:
Create a Layer named Ground, and add all the platforms in your
scene to that layer.
Create a bool variable
i.e
bool isGrounded;
Create a function to check if the character is grounded
Something like:
bool checkGrounded(){
return Physics.Raycast(transform.position, Vector3.down, 2f, 1 << LayerMask.NameToLayer("Ground")));
}
In this answer you can read about the involved parameters in the Raycast
Finally inside the update check if the player is grounded or not
Something like:
void Update(){
isGrounded = checkGrounded();
}
I have found that the isGrounded check can change over the course of the Update() function if you are checking it multiple times. Assigning it to a variable at the beginning of the function may solve the flickering issue.
void Update()
{
bool isGrounded = characterController.isGrounded;
...
I created an 3dobject and set a game object as target, and added the below code to main camera. I am able to zoom into the 3d object, but im not able to zoom out of it. How to zoom out? i.e to go back to original position.
using System.Collections;
using UnityEngine;
public class zoo22 : MonoBehaviour
{
public float movespeed = 35.0f;
//you need to say how far from the object the camera will stop
public float minimumDistanceFromTarget = 5f;
public GameObject targetobject;
private bool movingtowardstarget = false;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(1))
{
if (movingtowardstarget == true)
{
movingtowardstarget = false;
}
else
{
movingtowardstarget = true;
}
}
if (movingtowardstarget)
{
movetowardstarget(targetobject);
}
}
public void movetowardstarget(GameObject target)
{
if(Vector3.Distance(transform.position, target.transform.position) > minimumDistanceFromTarget) //we move only if we are further than the minimum distance
{
transform.position = Vector3.MoveTowards(transform.position, target.transform.position, movespeed * Time.deltaTime);
} else //otherwise, we stop moving
{
movingtowardstarget = false;
}
}
}
I not got your movingtoward bool but you can handle your zoom easy.
First rotate your camera to look at your object and later apply zoom:
For example to zoom whith the mouse Wheel in a ortho camera you need to handle orthographicSize:
int orthographicSizeMin = 1;
int orthographicSizeMax = 6;
function Update()
{
transform.LookAt(target);
if (Input.GetAxis("Mouse ScrollWheel") > 0) // forward
{
Camera.main.orthographicSize++;
}
if (Input.GetAxis("Mouse ScrollWheel") < 0) // back
{
Camera.main.orthographicSize--;
}
}
Camera.main.orthographicSize = Mathf.Clamp(Camera.main.orthographicSize, orthographicSizeMin, orthographicSizeMax );
For a perspective camera you need to handle field of view:
float minFov = 10f;
float maxFov = 90f;
float sensitivity = 10f;
function Update()
{
transform.LookAt(target);
float fov = Camera.main.fieldOfView;
fov += Input.GetAxis("Mouse ScrollWheel") * sensitivity;
fov = Mathf.Clamp(fov, minFov, maxFov);
Camera.main.fieldOfView = fov;
}
Easiest way imo:
Add object for original position as well:
public GameObject targetobject, originalPosObj;
Then pass it as target:
movetowardstarget(movingtowardstarget ? targetObject : originalPosObj);
you can use the same function to zoom in and zoom out. please check the example below. Enter negative velocity to move backwards.
void Update()
{
if (Input.GetMouseButtonDown(1)) //move backward
movetowardstarget(targetobject, true);
if (Input.GetMouseButtonDown(0)) //move forward
movetowardstarget(targetobject, false);
}
public void movetowardstarget(GameObject target, bool backwards)
{
float dir = backwards?-1.0f:1.0f;
actualDist = Vector3.Distance(transform.position, target.transform.position);
if (Vector3.Distance(transform.position, target.transform.position) > minimumDistanceFromTarget) //we move only if we are further than the minimum distance
{
transform.position = Vector3.MoveTowards(transform.position, target.transform.position, dir*movespeed * Time.deltaTime);
}
else //otherwise, we stop moving
{
movingtowardstarget = false;
}
}
I imagine you will want to do this will the Mouse Wheel.
public class CameraConrol : MonoBehaviour
{
Vector3 centerPosition;//positon of object you want to zoom in and out of
float MaxZoom = 3f;
void Update()
{
//mouse wheel chaned
if (Input.mouseScrollDelta.y !=0)
{
ZoomCamera();
}
}
public void ZoomCamera()
{
Vector3 newPosition = Vector3.MoveTowards(
transform.position, centerPosition, Input.mouseScrollDelta.y);
if(newPosition.y >= (centerPosition.y + MaxZoom ))
{
transform.position = newPosition;
}
}
}
I am working on a Character Controller Script and everything is working fine but the problem is that once my player starts to fall it is so sudden and jerks down. I would like the player to gradually fall down, this is my character controller script -
using UnityEngine;
using System.Collections;
public class CharacterController : MonoBehaviour {
public float inputDelay = 0.1f;
public float forwardVel = 12;
public float rotateCel = 12;
public float JumpHeight = 20;
public Vector3 Gravity = new Vector3 (0, -180, 0);
public bool CanPress;
private float jumpTime;
public float _initialJumpTime = 0.4f;
//[HideInInspector]
public bool isGrounded;
Quaternion targetRotation;
Rigidbody rBody;
Vector3 forwardInput, turnInput;
public bool HasJumped;
public Quaternion TargetRotation
{
get {return targetRotation;}
}
// Use this for initialization
void Start () {
Physics.gravity = Gravity;
targetRotation = transform.rotation;
if (GetComponent<Rigidbody> ())
rBody = GetComponent<Rigidbody> ();
else {
Debug.LogError("Character Needs Rigidbody");
}
// forwardInput = turnInput = 0;
forwardInput = turnInput = Vector3.zero;
}
// Update is called once per frame
void Update () {
GetInput ();
//Turn ();
if (CanPress == true) {
if (Input.GetKeyDown (KeyCode.Space)) {
HasJumped = true;
jumpTime = _initialJumpTime;
}
}
if (HasJumped == true) {
rBody.useGravity = false;
jumpTime -= 1 * Time.deltaTime;
if (jumpTime > 0) {
Jump();
}
else {
HasJumped = false;
rBody.useGravity = true;
}
}
}
void GetInput() {
//forwardInput = Input.GetAxis ("Vertical");
//turnInput = Input.GetAxis ("Horizontal");
forwardInput = new Vector3 (Input.GetAxis ("Horizontal") * rotateCel, 0, Input.GetAxis ("Vertical") * forwardVel);
forwardInput = transform.TransformDirection (forwardInput);
if (Input.GetKeyUp (KeyCode.Space)) {
//HasJumped = false;
}
}
void Jump() {
Vector3 up = transform.TransformDirection (Vector3.up);
GetComponent<Rigidbody> ().AddForce (up * 5, ForceMode.Impulse);
}
void FixedUpdate() {
Run ();
}
void Run() {
if (Mathf.Abs (10) > inputDelay) {
//Move
//rBody.velocity = transform.forward * forwardInput * forwardVel;
rBody.velocity = forwardInput;
} else {
//zero velocity
rBody.velocity = Vector3.zero;
}
}
void Turn() {
// targetRotation *= Quaternion.AngleAxis (rotateCel * turnInput * Time.deltaTime, Vector3.up);
// transform.rotation = targetRotation;
}
void OnTriggerEnter(Collider col) {
isGrounded = true;
CanPress = true;
}
void OnTriggerExit(Collider col) {
isGrounded = false;
CanPress = false;
}
}
My character has a Rigidbody attactches which uses gravity and has X,Y,Z constraints for Rotation.
The player goes up smoothly and falls down smoothly but the transition between the two is very abrupt and sudden.
Thanks for the help. :)
Okay, so I took your code and had a play.
I think the issue was that in your Run() function, you were altering the velocity of the rigidbody which was affecting your jumping.
I've taken that stuff out and improved your script slightly and tested it. Attach this to a capsule with a rigidbody on it, with a floor underneath with a box collider on and hit space, and you should get a smooth jump.
Your new(ish) script:
using UnityEngine;
using System.Collections;
public class CharacterController : MonoBehaviour
{
public float inputDelay = 0.1f;
public float forwardVel = 12;
public float rotateCel = 12;
public float jumpHeight = 10;
private float jumpTime;
public float _initialJumpTime = 0.4f;
//[HideInInspector]
public bool isGrounded;
Quaternion targetRotation;
Rigidbody rBody;
Vector3 forwardInput, turnInput;
public bool canJump;
public Quaternion TargetRotation
{
get { return targetRotation; }
}
void Start()
{
targetRotation = transform.rotation;
if (GetComponent<Rigidbody>())
rBody = GetComponent<Rigidbody>();
else
{
Debug.LogError("Character Needs Rigidbody");
}
// forwardInput = turnInput = 0;
forwardInput = turnInput = Vector3.zero;
}
void Update()
{
GetInput();
//Turn ();
if (Input.GetKeyDown(KeyCode.Space) && canJump)
{
rBody.AddForce(Vector3.up * jumpHeight, ForceMode.Impulse);
}
}
void GetInput()
{
//forwardInput = Input.GetAxis ("Vertical");
//turnInput = Input.GetAxis ("Horizontal");
forwardInput = new Vector3(Input.GetAxis("Horizontal") * rotateCel, 0, Input.GetAxis("Vertical") * forwardVel);
forwardInput = transform.TransformDirection(forwardInput);
}
void FixedUpdate()
{
//Run();
}
void Run()
{
//HERE YOU SET THE RIGIDBODYS VELOCITY, WHICH IS CAUSING YOUR JUMP TO NOT WORK PROPERLY. DO NOT MODIFY THE VELOCITY
//OF A RIGIDBODY
if (Mathf.Abs(10) > inputDelay)
{
//Move
//rBody.velocity = transform.forward * forwardInput * forwardVel;
rBody.velocity = forwardInput;
}
else
{
//zero velocity
rBody.velocity = Vector3.zero;
}
}
void Turn()
{
// targetRotation *= Quaternion.AngleAxis (rotateCel * turnInput * Time.deltaTime, Vector3.up);
// transform.rotation = targetRotation;
}
void OnCollisionEnter(Collision col)
{
isGrounded = true;
canJump = true;
}
void OnCollisionExit(Collision col)
{
isGrounded = false;
canJump = false;
}
}
Couple of points:
name your variables inThisKindOfFashion (jumpHeight, isOnGround, camelCaseExample), having variables beginning with a capital letter like Gravity and JumpHeight can get confusing.
as someone once answered on one of my questions, don't modify the velocity of a rigidbody unless you know what you are doing! Seems odd, but after following that advice I've never had a problem since!
In your script I have used OnCollision rather than OnTrigger. If you put a floor with a box collider underneath your capsule with a collider, rigidbody and this script on, your character will stop on the ground. If you use a trigger, he will fall through (at least in my experience!)
Happy coding! :-)
Edit
To respond to your comments:
"How do you suggest I move the player"
Movement can be done in a variety of different ways, but I usually use this one all the time unless I need to do something a bit differently:
void Update()
{
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
transform.position += Vector3.left * speed * Time.deltaTime; //speed could be 5f, for example (f means float);
}
// then do the same for other directions, RightArrow -.right, UpArrow - .forward, DownArrow - .back
}
"How do I adjust how fast the player jumps"
You can alter the jumpHeight variable for a higher or smaller jump. If by faster you mean falls down faster, go to Edit>Project Settings>Physics> and change Y gravity to something smaller, such as -20.
Tutorials can be found here
They have a wide variety of tutorials, and even have ones that come with example projects so you can just put it together following the video.