I want to be able to jump by pressing on space key inside a place like home or space station and also outside.
This is the player controller script attached to a capsule :
It was working fine until I added the jump part. At the top I added this 3 lines :
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
Then in the Update added :
if (controller.isGrounded && Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
But I don't have the variable controller.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float speed = 10.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
float translation = Input.GetAxis("Vertical") * speed;
float straffe = Input.GetAxis("Horizontal") * speed;
translation *= Time.deltaTime;
straffe *= Time.deltaTime;
transform.Translate(straffe, 0, translation);
if (controller.isGrounded && Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
if (Input.GetKeyDown("escape"))
{
Cursor.lockState = CursorLockMode.Locked;
}
}
}
And this is the cam mouse look script attached to the main camera that is child of the capsule :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamMouseLook : MonoBehaviour
{
public float sensitivity = 5.0f;
public float smoothing = 2.0f;
Vector2 mouseLook;
Vector2 smoothV;
GameObject character;
// Start is called before the first frame update
void Start()
{
character = this.transform.parent.gameObject;
}
// Update is called once per frame
void Update()
{
var md = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
md = Vector2.Scale(md, new Vector2(sensitivity * smoothing, sensitivity * smoothing));
smoothV.x = Mathf.Lerp(smoothV.x, md.x, 1f / smoothing);
smoothV.y = Mathf.Lerp(smoothV.y, md.y, 1f / smoothing);
mouseLook += smoothV;
mouseLook.y = Mathf.Clamp(mouseLook.y, -90f, 90f);
transform.localRotation = Quaternion.AngleAxis(-mouseLook.y, Vector3.right);
character.transform.localRotation = Quaternion.AngleAxis(mouseLook.x, character.transform.up);
}
}
Have you thought about applying a force?
public Rigidbody myphysic;
public float forceofjump = 100f; // or minor or more....
void Awake()
{
myphysic= transform.GetComponent<Rigidbody>();
}
void FixedUpdate()
{
if (controller.isGrounded && Input.GetButton("Jump"))
{
myphysic.AddForce( transform.up * forceofjump, ForceMode.Impulse);
}
}
Vector3.zero is wrong beacouse set all movement vector to zero! so = no actions!
or, exemple:
Vector3 moveDirection = new Vector3(0, 10, 0);
what does it mean:
new Vector3(X=stop, Y=10 of force, Z=stop);
Related
When i create room, and player 2 connect to room, i control him, and he controls me. What should I do?
Player controller combined with unity3d fps basicrigidbodypush script and mouse look.
Unity 3d 2020.3.26f version, development mode off. Video of it (left button and input field is creating room, right button and input field is joining room)https://dropmefiles.com/XPPa3.
In resources folder there is player prefab.
Player prefab contains mesh renderer, player controller script (below), character controller, photon view, photon transform view classic (synchronize position and rotation turned on), rigidbody and photon rigidbody view (all enabled)
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class PlayerController : MonoBehaviour
{
PhotonView view;
public LayerMask pushLayers;
public bool canPush;
[Range(0.5f, 5f)] public float strength = 1.1f;
public float jumpHeight = 3f;
public GameObject camera;
public LayerMask groundMask;
public Transform groundCheck;
public CharacterController controller;
public float speed = 10f;
public float gravity = -9.8f;
public float groundDistance = 0.4f;
Vector3 velocity;
bool isGrounded;
public Transform PlayerBody;
public float MouseSensitivity = 100f;
float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
Cursor.visible = false;
view = GetComponent<PhotonView>();
}
// Update is called once per frame
void Update()
{
if (view.IsMine) {
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if (isGrounded && velocity.y < 0) {
velocity.y = -7f;
}
if (isGrounded && Input.GetButtonDown("Jump")) {
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
if(Input.GetKeyDown(KeyCode.F)) {
CursorTrigger();
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
float mouseX = Input.GetAxis("Mouse X") * MouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * MouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
camera.transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
PlayerBody.Rotate(Vector3.up * mouseX);
}
}
private void PushRigidBodies(ControllerColliderHit hit)
{
if (view.IsMine) {
Rigidbody body = hit.collider.attachedRigidbody;
if (body == null || body.isKinematic) return;
var bodyLayerMask = 1 << body.gameObject.layer;
if ((bodyLayerMask & pushLayers.value) == 0) return;
if (hit.moveDirection.y < -0.3f) return;
Vector3 pushDir = new Vector3(hit.moveDirection.x, 0.0f, hit.moveDirection.z);
body.AddForce(pushDir * strength, ForceMode.Impulse);
}
}
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if (view.IsMine) {
if (canPush) PushRigidBodies(hit);
}
}
public void CursorTrigger() {
if (view.IsMine) {
Cursor.visible = !Cursor.visible;
}
}
}```
I usually go about this in a different way. Try the following:
if(!view.isMine)
{
return;
}
And then continue with your code afterwards.
I've got a problem with my spherical world player controller. It randomly jitter all the time.
Planet uses Mesh Collider, and it's rigidbody is set too: "is kinematic" and continous collisions.
Player's rigidbody is set to: "interpolate" and continous collisions.
Here is player controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[SerializeField] Transform cam, body, groundCheck;
[Space][SerializeField] float sensivity = 100f;
[SerializeField] float mass = 1f;
[SerializeField] float moveSpeed = 1f;
[SerializeField] float jumpHeight = 1f;
[SerializeField] LayerMask ground;
[SerializeField] float rotationChangeSpeed = 1f;
float xRotation = 0f;
Rigidbody rb;
Vector3 moveAmount, smoothMove;
Vector3 localUp;
bool grounded = false;
Quaternion targetRot;
float jumpTime = 0f;
Transform currentPlanet;
//On start
void Awake() {
Cursor.lockState = CursorLockMode.Locked;
rb = GetComponent<Rigidbody>();
}
//Physics simulation
void FixedUpdate() {
Grav();
FindingRotation();
Movement();
grounded = IsGrounded();
}
//Applying movement
void Movement() {
Vector3 localMove = transform.TransformDirection(moveAmount) * Time.fixedDeltaTime;
rb.MovePosition(rb.position + localMove);
}
//Simulating gravity
void Grav() {
List<CelestialBody> bodies = CelestialBody.bodies;
if(bodies.Count == 0) return;
Vector3 acceleration = Vector3.zero;
float maxForce = -1f;
for(int i = 0; i < bodies.Count; ++i) {
CelestialBody body = bodies[i];
float distance = Vector3.Distance(body.GetComponent<Transform>().position, transform.position);
float force = GravityManager.bigG * mass * body.mass / (distance * distance);
Vector3 direction = Vector3.Normalize(body.GetComponent<Transform>().position - transform.position);
if(force > maxForce) {
maxForce = force;
currentPlanet = body.transform;
}
acceleration += direction * force;
}
if(!grounded) GetComponent<Rigidbody>().AddForce(acceleration);
}
//Rotating according to body with highest gravity
void FindingRotation() {
localUp = Vector3.Normalize(transform.position - currentPlanet.position);
targetRot = Quaternion.FromToRotation(transform.up, localUp) * rb.rotation;
rb.rotation = Quaternion.Slerp(rb.rotation, targetRot, Time.fixedDeltaTime * rotationChangeSpeed);
}
//Per frame
void Update() {
CameraControls();
InputManager();
jumpTime -= Time.deltaTime;
}
//Camera controls
void CameraControls() {
float mouseX = Input.GetAxis("Mouse X") * sensivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * sensivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
cam.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
body.Rotate(Vector3.up * mouseX);
}
//Moving and jumping
void InputManager() {
Vector3 inputRaw = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")).normalized;
Vector3 input = inputRaw * moveSpeed;
moveAmount = Vector3.SmoothDamp(moveAmount, input, ref smoothMove, .15f);
if(grounded) {
if(Input.GetKeyDown(KeyCode.Space)) {
rb.AddForce(transform.up * jumpHeight, ForceMode.VelocityChange);;
jumpTime = .2f;
grounded = false;
}
else {
if(jumpTime <= 0f) rb.AddForce (-transform.up, ForceMode.VelocityChange);
}
}
}
//TODO: Improve with ray
bool IsGrounded() {
return (Physics.OverlapSphere(groundCheck.position, .1f, ground).Length > 0);
}
}
And here is Celestial Body:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CelestialBody : MonoBehaviour
{
public static List<CelestialBody> bodies = new List<CelestialBody>();
public float mass;
//public Vector3 speed;
void OnEnable() {
bodies.Add(this);
}
void OnDisable() {
bodies.Remove(this);
}
}
I will be really grateful for any advice.
I can't understand in any way that with the movement when the mouse is tilted down, I move backwards when I tilt up forward, as I realized this happens in the presence of gravity.
Most likely the problem is in FPSInput, since I tilted the player and deleted the MouseLook script, it didn't help
What it looks like: https://gifyu.com/image/AKcy
MouseLook:
using UnityEngine;
using System.Collections;
public class MouseLook : MonoBehaviour
{
public enum RotationAxes
{
MouseXAndY = 0,
MouseX = 1,
MouseY = 2
}
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityHor = 9.0f;
public float sensitivityVert = 9.0f;
public float minimumVert = -45.0f;
public float maximumVert = 45.0f;
private float _rotationX = 0;
void Start()
{
Rigidbody body = GetComponent<Rigidbody>();
if (body != null)
body.freezeRotation = true;
}
void Update()
{
if (axes == RotationAxes.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityHor, 0);
}
else if (axes == RotationAxes.MouseY)
{
_rotationX -= Input.GetAxis("Mouse Y") * sensitivityVert;
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert);
float rotationY = transform.localEulerAngles.y;
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0);
}
else
{
_rotationX -= Input.GetAxis("Mouse Y") * sensitivityVert;
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert);
float delta = Input.GetAxis("Mouse X") * sensitivityHor;
float rotationY = transform.localEulerAngles.y + delta;
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0);
}
}
}
FPSInput:
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(CharacterController))]
[AddComponentMenu("Control Script/FPS Input")]
public class FPSInput : MonoBehaviour
{
public float speed = 6.0f;
public float gravity = -9.8f;
private CharacterController _charController;
void Start()
{
_charController = GetComponent<CharacterController>();
}
void Update()
{
float deltaX = Input.GetAxis("Horizontal") * speed;
float deltaZ = Input.GetAxis("Vertical") * speed;
Vector3 movement = new Vector3(deltaX, 0, deltaZ);
movement = Vector3.ClampMagnitude(movement, speed);
movement.y = gravity;
movement *= Time.deltaTime;
movement = transform.TransformDirection(movement);
_charController.Move(movement);
}
}
You most probably do NOT want the gravity to be applied in local space. This way if you look up you move forward and if you look down you move backward.
Rather you want the User input be applied in local space but the Y axis to be taken in global space.
Rather do e.g.
var deltaX = Input.GetAxis("Horizontal");
var deltaZ = Input.GetAxis("Vertical");
var movement = new Vector3(deltaX, 0, deltaZ);
// Rather first clamp to 1, then multiply by the speed
movement = Vector3.ClampMagnitude(movement, 1) * speed;
// first convert local to global space
movement = transform.TransformDirection(movement);
// then overwrite the now global Y axis with the gravity
// This at the same time also prevents User from flying upwards
// when looking up and walking forward
movement.y = gravity;
_charController.Move(movement * Time.deltaTime);
I have a player in the game, which I can move using the keyboard and rotate only on the horizontal axis using the mouse. That means, I can aim only horizontally and I can not aim it up and down.
I have the Main Camera and another VM Camera from Cinemachine. The current state of the game is like this:
On the horizontal axis, I rotate the player, but on the vertical axis I only want the player's camera/FOV to be moved up and down.
My movement script attached to the player is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController characterController;
public float speed = 35f;
public Animator animator;
// camera and rotation
public Transform cameraHolder;
public float mouseSensitivity = 2f;
public float upLimit = 50;
public float downLimit = -50;
// gravity
private float gravity = 9.87f;
private float verticalSpeed = 0;
void Update()
{
Move();
Rotate();
}
public void Rotate()
{
float horizontalRotation = Input.GetAxis("Mouse X");
float verticalRotation = Input.GetAxis("Mouse Y");
transform.Rotate(0, horizontalRotation * mouseSensitivity, 0);
cameraHolder.Rotate(-verticalRotation * mouseSensitivity, 0, 0);
Vector3 currentRotation = cameraHolder.localEulerAngles;
if (currentRotation.x > 180) currentRotation.x -= 360;
currentRotation.x = Mathf.Clamp(currentRotation.x, upLimit, downLimit);
cameraHolder.localRotation = Quaternion.Euler(currentRotation);
}
private void Move()
{
float horizontalMove = Input.GetAxis("Horizontal");
float verticalMove = Input.GetAxis("Vertical");
if (characterController.isGrounded) verticalSpeed = 0;
else verticalSpeed -= gravity * Time.deltaTime;
Vector3 gravityMove = new Vector3(0, verticalSpeed, 0);
Vector3 move = transform.forward * verticalMove + transform.right * horizontalMove;
characterController.Move(speed * Time.deltaTime * move + gravityMove * Time.deltaTime);
}
}
This is the code i use, it works for me, it's super easy to implement, and stops moving the camera when you aren't focusing the game, is the script from one of Brackey's tutorials modified for this purpose:
using UnityEngine;
public class CameraController : MonoBehaviour
{
public PlayerController player;
public float sensitivity = 150f;
public float clampAngle = 85f;
public bool look = true;
private float verticalRotation;
private float horizontalRotation;
private void Start()
{
verticalRotation = transform.localEulerAngles.x;
horizontalRotation = player.transform.eulerAngles.y;
// Defines the state of the cursor
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
private void Update()
{
// Looks around if the user is in the window
if (look)
{
Look();
}
Debug.DrawRay(transform.position, transform.forward * 2, Color.red);
// If the player presses ESC while in the game, it unlocks the cursor
if (look && Input.GetKeyDown(KeyCode.Escape))
{
look = false;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
else if (Input.GetMouseButtonDown(0) && !look)
{
look = true;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
private void Look()
{
float _mouseVertical = -Input.GetAxis("Mouse Y");
float _mouseHorizontal = Input.GetAxis("Mouse X");
verticalRotation += _mouseVertical * sensitivity * Time.deltaTime;
horizontalRotation += _mouseHorizontal * sensitivity * Time.deltaTime;
verticalRotation = Mathf.Clamp(verticalRotation, -clampAngle, clampAngle);
transform.localRotation = Quaternion.Euler(verticalRotation, 0f, 0f);
player.transform.rotation = Quaternion.Euler(0f, horizontalRotation, 0f);
}
}
As seen in the video here: https://i.gyazo.com/ad45ef9e231fd2f9ec6d4cf76889aece.mp4
My code:
MouseLook.cs:
using UnityEngine;
using System.Collections;
public class MouseLook : MonoBehaviour
{
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 3F;
public float sensitivityY = 3F;
public Camera playerCamera;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
private float rotationX = 0F;
private float rotationY = 0F;
private Quaternion originalRotation;
void Update()
{
if (axes == RotationAxes.MouseXAndY)
{
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationX = ClampAngle(rotationX, minimumX, maximumX);
rotationY = ClampAngle(rotationY, minimumY, maximumY);
Quaternion xQuaternion = Quaternion.AngleAxis(rotationX, Vector3.up);
Quaternion yQuaternion = Quaternion.AngleAxis(rotationY, -Vector3.right);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
}
if (axes == RotationAxes.MouseX)
{
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationX = ClampAngle(rotationX, minimumX, maximumX);
Quaternion xQuaternion = Quaternion.AngleAxis(rotationX, Vector3.up);
transform.localRotation = originalRotation * xQuaternion;
}
if (axes == RotationAxes.MouseY || playerCamera != null)
{
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = ClampAngle(rotationY, minimumY, maximumY);
Quaternion yQuaternion = Quaternion.AngleAxis(-rotationY, Vector3.right);
if (playerCamera != null)
{
playerCamera.transform.localRotation = originalRotation * yQuaternion;
}
else
{
transform.localRotation = originalRotation * yQuaternion;
}
}
}
void Start()
{
/*
if (gameObject.GetComponent<Rigidbody>())
{
gameObject.GetComponent<Rigidbody>().freezeRotation = true;
}
*/
originalRotation = transform.localRotation;
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360F)
{
angle += 360F;
}
if (angle > 360F)
{
angle -= 360F;
}
return Mathf.Clamp(angle, min, max);
}
}
FirstPersonController.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using Cursor = UnityEngine.Cursor;
public class FirstPersonController : MonoBehaviour
{
private float speed = 5;
private float jumpPower = 4;
Rigidbody rb;
CapsuleCollider col;
public GameObject crossHair;
bool isActive;
float HorizontalInput;
float VerticalInput;
void Start()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
rb = GetComponent<Rigidbody>();
col = GetComponent<CapsuleCollider>();
crossHair = GameObject.FindWithTag("CrossHair");
}
void Update()
{
HorizontalInput = Input.GetAxisRaw("Horizontal");
VerticalInput = Input.GetAxisRaw("Vertical");
if (Input.GetKeyDown("escape"))
{
Cursor.lockState = CursorLockMode.None;
}
if (Input.GetButtonDown("Sprint"))
{
speed = 15;
}
if (Input.GetButtonUp("Sprint"))
{
speed = 5;
}
if (Input.GetKeyDown(KeyCode.H))
{
isActive = !isActive;
}
if (isActive)
{
crossHair.SetActive(true);
}
else
{
crossHair.SetActive(false);
}
}
void FixedUpdate()
{
Vector3 xMovement = transform.right * speed * HorizontalInput * Time.deltaTime;
Vector3 zMovement = transform.forward * speed * VerticalInput * Time.deltaTime;
rb.velocity = new Vector3(HorizontalInput, 0, VerticalInput) * speed;
if (isGrounded() && Input.GetButtonDown("Jump"))
{
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
private bool isGrounded()
{
return Physics.Raycast(transform.position, Vector3.down, col.bounds.extents.y + 0.1f);
}
}
Is there anything wrong I am doing in this code, if so how do I fix it?
Entire project can be downloaded here: https://github.com/Some-T/FirstPersonController-CSharp
Project has relevant colliders and rigidbodies set up!
Someone has advised me to use shapecast, but I believe that may incorrect? I can't see how that would work as my player does not have character controller component added to it?
Overall how do I stop my first person character controller going through the wall like in the initial video specified above?
Upon further research I have discovered the following:
The answer is to use:
https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html as a quick fix.
But definitively for flawlessness use:
https://docs.unity3d.com/ScriptReference/Rigidbody-velocity.html
As to how in C# I am not so sure, but here is a screen shot I did in bolt asset.
Currently I have movmement working with velocity but it does not work properly, not sure as to why? So overall my question now is how do I get movement working using velocity? I added a line in FirstPersonController.cs that moves the character using velocity of rb.velocity = new Vector3(HorizontalInput, 0, VerticalInput) * speed; so my only question and issue now is my player does not move in the direction the camera on my player is facing so I am not sure how to fix this specific thing overall?
In your project code is different from one that you provided here.
Try to enable rigidbody`s rotation constraint - freeze X and Z rotation, leave only Y. When you rotate your capsule collider (as it works in your project), it can "climb" on a wall.
Do the isGrounded check when you move, and lock movement, if not grounded.
Try to increase Collider.contactOffset
If above does not helps, try to use Rigidbody.velocity instead of Rigidbody.MovePosition.
You can also reduce Rigidbody.drag
In general, pretty good technique is to use NavMesh for movement - in this way, you able to explicitly lock player from movement outside of navmesh surface. But, of course, it doesn`t fit to many gameplays.
Hope, it helps.
upd
You move your player like this:
void FixedUpdate()
{
Vector3 xMovement = transform.right * speed * HorizontalInput * Time.deltaTime;
Vector3 zMovement = transform.forward * speed * VerticalInput * Time.deltaTime;
}
Note, that you not even apply it to rigidbody;
But you get your input this way:
float HorizontalInput = Input.GetAxis("Horizontal");
float VerticalInput = Input.GetAxis("Vertical");
in Update, so input just stays inside Update, and does not applied at all. You declared your variables twice, once on class top, another in Update().