void UpdateMovement()
{
Vector2 targetDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
targetDir.Normalize();
currentDir = Vector2.SmoothDamp(currentDir, targetDir, ref currentDirVelocity, moveSmoothTime);
if (controller.isGrounded)
{
velocityY = -gravity;
}
// jump
if (controller.isGrounded && Input.GetKeyDown(KeyCode.Space))
{
velocityY = jumpForce;
}
// sprint
if (Input.GetKey(KeyCode.LeftShift))
{
velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * sprintSpeed + Vector3.up * velocityY;
}
else
{
velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * walkSpeed + Vector3.up * velocityY;
}
velocityY -= gravity * Time.deltaTime;
Debug.Log(velocityY);
controller.Move(velocity * Time.deltaTime);
}
This is the code that I am using to move and jump in my game. Those functions work fine, the problem is in the gravity when walking off a surface. When jumping gravity works as intended but when falling without jumping (walking off the edge) gravity is still set to it's default value (15) so the characters falls incredibly fast.
I understand that this is caused by having no function to change this value when falling from an edge but I have found no way of making this happen without breaking all of the vertical movement.
You can reset the gravity as Brackeys did in his FPS Controller Tutorial:
if (isGrounded) {
velocityY = -2f;
}
Related
How can I shorten this code and avoid copying, what do you advise?
The method is used to move the camera in space using buttons
private void HandleMovementInput() {
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
new_position += (transform.forward * movement_speed);
}
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
new_position += (transform.forward * -movement_speed);
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
new_position += (transform.right * movement_speed);
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
new_position += (transform.right * -movement_speed);
}
if (Input.GetKey(KeyCode.Q))
{
new_rotation *= Quaternion.Euler(Vector3.up * rotation_amount);
}
if (Input.GetKey(KeyCode.E))
{
new_rotation *= Quaternion.Euler(Vector3.up * -rotation_amount);
}
//Shit code for zoom
if (Input.GetKey(KeyCode.R))
{
new_zoom += zoom_amount;
}
if (Input.GetKey(KeyCode.F))
{
new_zoom -= zoom_amount;
}
transform.position = Vector3.Lerp(transform.position, new_position, Time.deltaTime * movement_time);
transform.rotation = Quaternion.Lerp(transform.rotation, new_rotation, Time.deltaTime * movement_time);
camera_transform.localPosition = Vector3.Lerp(camera_transform.localPosition,new_zoom, Time.deltaTime * movement_time);
}
Unfortunately, I'm not so strong in Unity to solve this architectural case.
Try using Input.Getaxis.
https://docs.unity3d.com/ScriptReference/Input.GetAxis.html
I used this code for my player movement script
//playerinput is a Vector3 variable
playerinput = new Vector3(Input.GetAxis("Horizontal"), 0f,
Input.GetAxis("Vertical"));
//transform.TransformDirection is here to move the player depending in their rotation
//playerinput.normalized is there for stopping strafing(for example, holding w and s together makes the player faster)
//I don't think you should change Mathf.Clamp01(playerinput.magnitude). This is very important for the movement to look good.
Vector3 movevector = transform.TransformDirection(playerinput.normalized * Mathf.Clamp01(playerinput.magnitude)) * speed;
//rb is the rigidbody by the way. Add rigidbody component to your camera
rb.velocity = new Vector3(movevector.x, rb.velocity.y, movevector.z);
This will do the trick, you can remove some lines of code to fit your game. Hope this helped!
I can make the camera move the way I want, but I need it to be confined to within the 3D hollow sphere that I created. Currently the player can fly the camera out of the game area.
I've tried parenting the camera to a spherical game object, but the camera still leaves the game area but the sphere stays inside.
This was my attempt at using the BoundingSphere method to keep the camera inside the sphere.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SphericalBoundary : MonoBehaviour
{
public Vector3 pos;
public float r;
void Start()
{
BoundingSphere();
}
private void FixedUpdate()
{
BoundingSphere();
}
public void BoundingSphere()
{
pos = new Vector3(0, 0, 0);
r = (100);
}
}
============================================================================
============================================================================
This is the script that makes the camera fly around. Works perfectly.
using UnityEngine;
using System.Collections;
public class CameraFlight : MonoBehaviour
{
/*
EXTENDED FLYCAM
Desi Quintans (CowfaceGames.com), 17 August 2012.
Based on FlyThrough.js by Slin (http://wiki.unity3d.com/index.php/FlyThrough), 17 May 2011.
LICENSE
Free as in speech, and free as in beer.
FEATURES
WASD/Arrows: Movement
Q: Climb
E: Drop
Shift: Move faster
Control: Move slower
End: Toggle cursor locking to screen (you can also press Ctrl+P to toggle play mode on and off).
*/
public float cameraSensitivity = 90;
public float climbSpeed = 4;
public float normalMoveSpeed = 10;
public float slowMoveFactor = 0.25f;
public float fastMoveFactor = 3;
private float rotationX = 0.0f;
private float rotationY = 0.0f;
void Start()
{
// Screen.lockCursor = true;
}
void Update()
{
rotationX += Input.GetAxis("Mouse X") * cameraSensitivity * Time.deltaTime;
rotationY += Input.GetAxis("Mouse Y") * cameraSensitivity * Time.deltaTime;
rotationY = Mathf.Clamp(rotationY, -90, 90);
transform.localRotation = Quaternion.AngleAxis(rotationX, Vector3.up);
transform.localRotation *= Quaternion.AngleAxis(rotationY, Vector3.left);
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
{
transform.position += transform.forward * (normalMoveSpeed * fastMoveFactor) * Input.GetAxis("Vertical") * Time.deltaTime;
transform.position += transform.right * (normalMoveSpeed * fastMoveFactor) * Input.GetAxis("Horizontal") * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
{
transform.position += transform.forward * (normalMoveSpeed * slowMoveFactor) * Input.GetAxis("Vertical") * Time.deltaTime;
transform.position += transform.right * (normalMoveSpeed * slowMoveFactor) * Input.GetAxis("Horizontal") * Time.deltaTime;
}
else
{
transform.position += transform.forward * normalMoveSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
transform.position += transform.right * normalMoveSpeed * Input.GetAxis("Horizontal") * Time.deltaTime;
}
if (Input.GetKey(KeyCode.Q)) { transform.position += transform.up * climbSpeed * Time.deltaTime; }
if (Input.GetKey(KeyCode.E)) { transform.position -= transform.up * climbSpeed * Time.deltaTime; }
//if (Input.GetKeyDown(KeyCode.End))
//{
// Screen.lockCursor = (Screen.lockCursor == false) ? true :][1]
false;
//}
}
}
No errors are showing up. During play the player can fly the camera out of the sphere but I want them confined to the sphere.
I think you must look your camera position on every frame and also check if it's going out of bound of the sphere here is some code which might help you(it is not tested)
public class TestScriptForStackOverflow : MonoBehaviour {
public Transform CameraTrans, SphereTrans;
private float _sphereRadius;
void Start() {
//if we are talking about sphere its localscale.x,y,z values are always equal
_sphereRadius = SphereTrans.localScale.x / 2;
}
void Update() {
if (IsOutsideTheSphere(_sphereRadius, CameraTrans.position, SphereTrans.position)) {
//lets find direction of camera from sphere center
Vector3 direction = (CameraTrans.position - SphereTrans.position).normalized;
//this is bound point for specific direction which is point is on the end of the radius
Vector3 boundPos = SphereTrans.position + direction * _sphereRadius;
//finally assign bound position to camera to stop it to pierce the sphere bounds
CameraTrans.position = boundPos;
}
}
private bool IsOutsideTheSphere(float sphereRadius, Vector3 cameraPosition, Vector3 sphereCenterPosition) {
//distance betweeen cameraPosition and sphereCenterPosition
float distanceBetween = (cameraPosition - sphereCenterPosition).magnitude;
//returns true if distance between sphere center and camera position is longer then sphere radius
return distanceBetween > sphereRadius;
}
If there is something you don't understand ask me in comments
I'm trying to create a character controller that allows the movement speed to be affected by how far the player is pressing the left stick. When I can get that much to work, the other issue I encounter is the players speed decreasing while moving diagonally.
Most of the information I've found online deal with the opposite issue where diagonal movement is faster (movement vector goes above 1). The solution there would be to clamp the magnitude so pressing the stick into a corner doesn't go above 1. I've tried clamping to see if that would work, however, I don't believe that's the solution to my problem.
The code here allows the player to move in relation to the camera and the speed is influenced by input vector.
Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 inputDir = input.normalized;
void Move(Vector3 inputDir, Vector3 input)
{
running = Input.GetKey(KeyCode.Joystick1Button1); // B button on xbox one controller
// Rotation stuff
if (inputDir != Vector3.zero) {
float targetRotation = Mathf.Atan2(inputDir.x, inputDir.z) * Mathf.Rad2Deg + cameraTransform.eulerAngles.y;
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
}
// Pretty sure this is where things are breaking
float targetSpeed = ((running) ? runSpeed : walkSpeed) * inputDir.magnitude;
currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
currentSpeed *= input.magnitude;
vel = transform.forward * currentSpeed + Vector3.up * velocityY;
currentSpeed = new Vector3(_controller.velocity.x, 0, _controller.velocity.z).magnitude;
}
void ExecuteMovement()
{
_controller.Move(vel * Time.deltaTime);
}
I am starting a new unity3d project and i want to know how to rotate moving forward spaceship from y-axis to left and right.
void Update(){
transform.position += transform.forward * Time.deltaTime * 10f;
if(input.Getkey(KeyCode.LeftArrow))
{
//code for rotate ;
}
}
I want that when I press arrow left key then spaceship rotates from y-axis to left until the arrow key released.
You can use Transform.Rotate(Vector3).
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow))
transform.Rotate(transform.forward * 3);
if (Input.GetKey(KeyCode.RightArrow))
transform.Rotate(transform.forward * -3);
}
I dont really know if i understand the question, but I think this may help you.
void Update () {
if (Input.GetKeyDown (KeyCode.Space)){
transform.Rotate (new Vector3(Time.deltaTime * 0, 1, 0));
}
where the first 0 is for x-axis, number 1 is for y-axis and the other 0 is for z-axis
You'll want declare the speed and rotation speed as floats so you can easily change them later, but here you go. I did both left and right.
float speed = 10.0f;
float rotateSpeed = 2.0f;
void Update(){
transform.position += transform.forward * Time.deltaTime * speed;
if(Input.GetKeyDown(KeyCode.LeftArrow))
{
//code for rotate
transform.Rotate(vector3.left * Time.deltaTime * rotateSpeed);
}
else if(Input.GetKeyDown(KeyCode.RightArrow))
{
transform.Rotate(vector3.right * Time.deltaTime * rotateSpeed);
}
}
If you want to rotate the ship relative to the world then use:
transform.Rotate(vector3.left * Time.deltaTime * rotateSpeed, Space.World);
I'm currently working on a pushing system and I'm having some issues. The player uses a CharacterController which can interact with Rigidbodies in the scene. Currently this works as follows: When a Raycast hits a pushable object in front of the player and presses the push button he will push the object, which all works fine. The issue occurs when the Player is slightly turned away from the pushable and starts pushing. I.e. when the character is off by like 10 degrees, but the ray still hits. The concept I had in mind was calculating the angle of the raycast that hits the pushable cube and rotating the character controller towards the pushable by that angle. The problem is I have no clue how to achieve this. I hope someone can help me with this concept. If anyone has any other concepts or ideas feel free to share them :)
Edit: I've added some scripts
The Character controller part:
if (inputDir != Vector2.zero)
{
float targetRotation = Mathf.Atan2(inputDir.x, inputDir.y) * Mathf.Rad2Deg + cameraT.eulerAngles.y;
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, GetModifiedSmoothTime(turnSmoothTime));
}
float targetSpeed = ((running) ? runSpeed : movementSpeed) * inputDir.magnitude;
currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
velocityY += Time.deltaTime * gravity;
Vector3 velocity = transform.forward * currentSpeed + Vector3.up * velocityY;
controller.Move(velocity * Time.deltaTime);
currentSpeed = new Vector2(controller.velocity.x, controller.velocity.z).magnitude;
The Raycast setup and pushstates as off now:
if (Physics.Raycast(middle, (forward), out hit, distanceForPush))
{
if (Input.GetButton("Push") && hit.collider.tag == "PushableLight")
{
anim.SetBool("isPushing", true);
pushForce = playerPushForceLight;
movementSpeed = pushSpeedLight;
hit.transform.SendMessage("HitByPlayer", null, SendMessageOptions.DontRequireReceiver);
if (controller.velocity == Vector3.zero)
{
anim.SetFloat("pushSpeedAnim", 0f);
}
else
{
anim.SetFloat("pushSpeedAnim", 1f);
}
}
else if (Input.GetButton("Push") && hit.collider.tag == "PushableHeavy")
{
anim.SetBool("isPushing", true);
pushForce = playerPushForceHeavy;
movementSpeed = pushSpeedHeavy;
hit.transform.SendMessage("HitByPlayer", null, SendMessageOptions.DontRequireReceiver);
if (controller.velocity == Vector3.zero)
{
anim.SetFloat("pushSpeedAnim", 0f);
}
else
{
anim.SetFloat("pushSpeedAnim", 1f);
}
}
else
{
anim.SetBool("isPushing", false);
pushForce = 0f;
movementSpeed = walkSpeed;
hit.transform.SendMessage("HitStopped", null, SendMessageOptions.DontRequireReceiver);
}
}
else
{
anim.SetBool("isPushing", false);
}
AnimatorStateInfo stateInfo = anim.GetCurrentAnimatorStateInfo(0);
if (stateInfo.fullPathHash == pushStateHash)
{
turnSmoothTime = maxTurnSmoothTimePushing;
}
else
{
turnSmoothTime = 0.1f;
}
}
I would try to align the player with the hit's collision normal.
transform.rotation = Quaternion.LookRotation(-hit.normal, Vector3.up);
This will probably only work well for boxes, though.