How should I configure the Sprint in the InputManager? - c#

This script is attached to Player object:
using UnityEngine;
using System.Collections;
[RequireComponent (typeof (Rigidbody))]
[RequireComponent (typeof (BoxCollider))]
public class PlayerController : MonoBehaviour {
public float walkSpeed = 6;
public float runSpeed = 10;
public float strafeSpeed = 5;
public float gravity = 20;
public float jumpHeight = 2;
public bool canJump = true;
private bool isRunning = false;
private bool isGrounded = false;
public bool IsRunning
{
get { return isRunning; }
}
void Awake () {
GetComponent<Rigidbody>().freezeRotation = true;
GetComponent<Rigidbody>().useGravity = false;
}
void FixedUpdate () {
// get correct speed
float forwardAndBackSpeed = walkSpeed;
// if running, set run speed
if (isRunning) {
forwardAndBackSpeed = runSpeed;
}
// calculate how fast it should be moving
Vector3 targetVelocity = new Vector3(Input.GetAxis("Horizontal") * strafeSpeed, 0, Input.GetAxis("Vertical") * forwardAndBackSpeed);
targetVelocity = transform.TransformDirection(targetVelocity);
// apply a force that attempts to reach our target velocity
Vector3 velocity = GetComponent<Rigidbody>().velocity;
Vector3 velocityChange = (targetVelocity - velocity);
velocityChange.y = 0;
GetComponent<Rigidbody>().AddForce(velocityChange, ForceMode.VelocityChange);
// jump
if (canJump && isGrounded && Input.GetButton("Jump")) {
GetComponent<Rigidbody>().velocity = new Vector3(velocity.x, Mathf.Sqrt(2 * jumpHeight * gravity), velocity.z);
isGrounded = false;
}
// apply gravity
GetComponent<Rigidbody>().AddForce(new Vector3 (0, -gravity * GetComponent<Rigidbody>().mass, 0));
}
void Update() {
// check if the player is touching a surface below them
checkGrounded();
// check if the player is running
if (isGrounded && Input.GetButtonDown("Sprint")) {
isRunning = true;
}
// check if the player stops running
if (Input.GetButtonUp("Sprint")) {
isRunning = false;
}
}
void checkGrounded() {
/* ==============
* REMEMBER
* ==============
* If you change the size of the prefab, you may have
* to change the length of the ray to ensure it hits
* the ground.
*
* All obstacles/walls/floors must have rigidbodies
* attached to them. If not, Unity physics may get
* confused and the player can jump really high
* when in a corner between 2 walls for example.
*/
float rayLength = 0.7f;
RaycastHit hit;
Ray ray = new Ray(transform.position, -transform.up);
//Debug.DrawRay(ray.origin, ray.direction * rayLength);
// if there is something directly below the player
if (Physics.Raycast(ray, out hit, rayLength)) {
isGrounded = true;
}
}
}
There are some parts in the script it's using "Sprint"
For example:
// check if the player is running
if (isGrounded && Input.GetButtonDown("Sprint")) {
isRunning = true;
}
// check if the player stops running
if (Input.GetButtonUp("Sprint")) {
isRunning = false;
}
But "Spring" is not defined in the editor input:
Edit > Project Settings > Input:
I can change the size in the Input Manager to 19 and it will duplicate the Cancel so I changed the name to Sprint. But what should be the config for the Sprint ? It's now the Cancel config.
When running the game I'm getting this exception:
ArgumentException: Input Button Sprint is not setup.
To change the input settings use: Edit -> Project Settings -> Input
PlayerController.Update () (at Assets/My Scripts/Character1/PlayerController.cs:62)

This might sound silly, but did you save your project? If you save your scene, that is different than saving your project which is where the Project Settings are located.
File -> Save Scene (CTRL + S) is different than File -> Save Project

So this may be very old but I'm going to respond for those that may still be searching in vain:
When adding or changing an input in input manager to "Sprint". It would cause me an error saying it was not set up even if I placed correct naming conventions for every positive or negative button even the alts.
The only fix was to change the name from "Sprint" to "Run" or just about anything works except for "Sprint" for whatever crazy Unity reason there is. Hope this helps those that have been going insane like I did when I first encountered this.

Related

how to set up a first person character controller's movement

im trying to make a first person character controller for a game im making, it wont need jumping nor fast speeds or any additional moves, practically just walking and a weapon swinging ill add down the line, right now though first person is out of my comfort zone, i made a third person character controller and it wasnt THIS difficult, im basically trying to change the forward vector of the player capsule into something more compatable with input.getaxis, i currently have a frankenstien mess that hardly functions, but the camera movement functions just fine, with my current setup i am using a rigidbody to control the player, and i idealy want to use velocity and not addforce or moveposition, velocity has given me the best results so far, how can i fix my movement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class characterController : MonoBehaviour {
//variables and functions
public float moveSpeed = 0.1f;
public bool tweening = false;
public bool jumping = false;
public bool reteleporing = false;
bool walking = false;
public bool ragdolled = false;
public Vector3 smoothedvel;
public Vector3 smoothedrotationalvector;
public Vector3 cameraoffset;
void Start () {
cameraoffset = new Vector3(0,0,0);
smoothedvel = new Vector3(0,0,0);
moveSpeed = 5;
}
void Update (){
//movement
smoothedrotationalvector = Vector3.Lerp(smoothedrotationalvector, new Vector3(-Input.GetAxis("Vertical"),0,Input.GetAxis("Horizontal")), 0.2f);
if (new Vector3(Input.GetAxis("Vertical"),0,Input.GetAxis("Horizontal")).magnitude != 0)
{
transform.LookAt(GameObject.Find("Main Camera").GetComponent<Camera>().transform.position, -Vector3.up);
transform.localEulerAngles = new Vector3(0,transform.localEulerAngles.y,0);
}
if (transform.position.y < -100)
{
reteleporing = true;
}
if (reteleporing == true)
{
transform.position = GameObject.Find("spawnpos").transform.position;
}
if (transform.position.y > 2.4)
{
reteleporing = false;
}
if (reteleporing == false)
{
if (new Vector3(Input.GetAxis("Vertical"),0,Input.GetAxis("Horizontal")).magnitude != 0)
{
float axisX = Input.GetAxis("Horizontal") * moveSpeed;
float axisZ = Input.GetAxis("Vertical") * moveSpeed;
Vector3 moveDirection = transform.right * axisX + transform.forward * axisZ;
gameObject.GetComponent<Rigidbody>().velocity = moveDirection;
}
}
if (new Vector3(Input.GetAxis("Vertical"),0,Input.GetAxis("Horizontal")).magnitude != 0 & walking == false)
{
walking = true;
}
if (new Vector3(Input.GetAxis("Vertical"),0,Input.GetAxis("Horizontal")).magnitude == 0 & walking == true)
{
walking = false;
}
GameObject.Find("Main Camera").GetComponent<Camera>().transform.position = transform.position;
}
}
i solved it, i used addforce instead of velocity and messed around with it from there, turns out velocity is really bad for things like this, it just downright didnt work because of velocity alone from what i can tell, another somewhat major thing was the switch from getaxis to getaxisraw, made it alot more snappy.

How to make a wallrun in unity

I`m trying to make a wallrun in unity like the wallrun of the Prince of Persia.
The idea is that when you are touching the wall and you press "left shift" the player would run some seconds without falling.
I would like to add that if you press "enter" the character would jump to the side using the Wall as support for impulse.
You can watch this in the first minutes of the video:
https://www.youtube.com/watch?v=zsnB7HEiLr0
I have made this script for the character controller:
public Transform playerPosition;
//controls the x movement. (right/left)
public float horizontalmove;
//controls the y movement. (forward/back)
public float verticalmove;
//controls the movement direction.
private Vector3 playerInput;
//Here I store my character controller.
public CharacterController player;
//controls the player speed.
public float playerSpeed;
//controls de movement direction according to camera
public Vector3 movePlayer;
//controls the last movement
public Vector3 lastMovePlayer;
public float gravity = 9.8f;
public float fallVelocity;
public float jumpForce = 5.0f;
public float verticalSpeed;
private RaycastHit HitR;
private RaycastHit HitL;
//Here I store the main camera
public Camera mainCamera;
//It stores the camera direction when the player is looking forward.
private Vector3 camForward;
//It stores the camera direction when the player is looking right.
private Vector3 camRight;
//Checks
//The meaning of Caida is fall.
public bool Caida;
//The meaning of salto is jump.
public bool Salto;
public bool Wallrun;
public bool WallrunCount;
// Start is called befoe the first frame update
void Start()
{
//i store the character controler.
player = GetComponent<CharacterController>();
Caida = true;
}
// Update is called once per frame
void Update()
{
if (Wallrun == true)
{
Caida = false;
}
if (Salto == true)
{
fallVelocity -= gravity * Time.deltaTime;
movePlayer = lastMovePlayer;
}
if (Caida == true)
{
fallVelocity -= gravity * Time.deltaTime;
}
if (player.isGrounded && Wallrun == false)
{
Caida = false;
Salto = false;
WallrunCount = false;
//I assign the horizontal move to the w and s keys.
horizontalmove = Input.GetAxis("Horizontal");
//I assign the vertical move to the a and d keys.)
verticalmove = Input.GetAxis("Vertical");
//controls the movement direction
playerInput = new Vector3(horizontalmove, 0, verticalmove);
//limits the player speed. With this method if teh player waalks in diagonal doesn´t
//exceed the speed limit.
playerInput = Vector3.ClampMagnitude(playerInput, 1);
// It calls the function that give the camera look direction.
camDirection();
//Here, It`s calculates the player movement considering the camera point and the movement
//we have assing to teh player earlier
//With this method the player always moves looking to the camera
movePlayer = playerInput.x * camRight + playerInput.z * camForward;
//The movement * the speed we want.
movePlayer = movePlayer * playerSpeed;
//we are going to say to the player where is looking at.
player.transform.LookAt(player.transform.position + movePlayer);
//It gives the gravity to the player.
fallVelocity = -gravity * Time.deltaTime;
if (Input.GetKeyDown(KeyCode.Space))
{
Salto = true;
fallVelocity = jumpForce;
}
}
else if (!player.isGrounded && Salto == false && Wallrun == false)
{
Caida = true;
}
movePlayer.y = fallVelocity;
//we give the movement to th eplayer.
player.Move(movePlayer * Time.deltaTime);
lastMovePlayer = movePlayer;
}
private void OnTriggerStay(Collider other)
{
if (Input.GetKeyDown(KeyCode.LeftShift) && Wallrun == false && WallrunCount == false)
{
if (Input.GetKey("w"))
{
Wallrun = true;
WallrunCount = true;
fallVelocity = 5f;
movePlayer.y = fallVelocity;
movePlayer.z = movePlayer.z * 1.6f;
if (Physics.Raycast(transform.position, transform.right, out HitR, 1))
{
movePlayer.x = 1.6f;
}
else if (Physics.Raycast(transform.position, -transform.right, out HitL, 1))
{
movePlayer.x = -1.6f;
}
StartCoroutine(wallrunTime());
}
}
}
void camDirection()
{
//we store the forward and right directions here.
camForward = mainCamera.transform.forward;
camRight = mainCamera.transform.right;
//we block the direction and the camera direction because we are not going to use it.
camForward.y = 0;
camRight.y = 0;
//It gives as the normalized vectors.
camForward = camForward.normalized;
camRight = camRight.normalized;
}
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if (!player.isGrounded && hit.normal.y < 0.1f)
{
if (Input.GetKeyDown(KeyCode.Space))
{
fallVelocity = jumpForce;
movePlayer = hit.normal * 7;
player.transform.LookAt(player.transform.position + movePlayer);
}
}
}
IEnumerator wallrunTime()
{
yield return new WaitForSeconds(1);
Wallrun = false;
}
As you can see, when the player enters the leftshift it checks to what direction is moving the character, if this is front (w) the script make the z movement * 1.6 (to make the character run a bit in the wall) and the character go a bit up bit the y axis.Then, the script checks if the Wall it i son the right or on the left and, depending on where the wall is, sticks the character to that wall.
private void OnTriggerStay(Collider other)
{
if (Input.GetKeyDown(KeyCode.LeftShift) && Wallrun == false && WallrunCount == false)
{
if (Input.GetKey("w"))
{
Wallrun = true;
WallrunCount = true;
fallVelocity = 5f;
movePlayer.y = fallVelocity;
movePlayer.z = movePlayer.z * 1.6f;
if (Physics.Raycast(transform.position, transform.right, out HitR, 1))
{
movePlayer.x = 1.6f;
}
else if (Physics.Raycast(transform.position, -transform.right, out HitL, 1))
{
movePlayer.x = -1.6f;
}
StartCoroutine(wallrunTime());
}
}
}
With this method, I can make the character jump when the player enters space because the character is hitting the wall (a condition required to bounce in the wall).
And after some seconds, the character falls simulating a wallrun.
IEnumerator wallrunTime()
{
yield return new WaitForSeconds(1);
Wallrun = false;
}
The problem is that this works perfectly if the character makes the wallrun when is looking in the same direction as the axes of the environment.
When the character z axis is looking at the same direction of the environment z axes it works perfectly. But when the axes are not looking at the same direction is a disaster. I show you a video I have recorded.
https://youtu.be/KH7rE9kh5d0
The problem, I suppose, is that with the code I have written, I'm moving the character according to the axes of the environment, and not its axes, so I have to tell him to move according to his own.
My teacher says I might have to change the way I make the character move. I would like to know if you can tell me a way to fix this without changing the movement method or if it is not possible, how can I change that movement.
Thank you in advance.

Why when using a break point the script will continue and will work fine but without a break point it will not?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
public class SpaceshipCutscene : MonoBehaviour
{
public Transform player;
public Transform[] npcs;
public Transform console;
public Camera FPSCamera;
public Camera mainCamera;
public Animator[] anim;
public float rotationSpeed = 3f;
public float distanceFromConsole;
private bool moveNpc = false;
private float sp = 0f;
private float distance;
// Use this for initialization
void Start()
{
}
private void Update()
{
distance = Vector3.Distance(transform.position, npcs[0].transform.position);
if (moveNpc)
{
// Soldier 2 rotating and looking at player
Vector3 dir = player.position - npcs[0].position;
dir.y = 0; // keep the direction strictly horizontal
Quaternion rot = Quaternion.LookRotation(dir);
// slerp to the desired rotation over time
npcs[0].rotation = Quaternion.Slerp(npcs[0].rotation, rot, rotationSpeed * Time.deltaTime);
var dist = Vector3.Distance(npcs[1].position, console.position);
if (dist < distanceFromConsole)
{
sp += Time.deltaTime;
sp = Mathf.Clamp(sp, 0f, 1f);
anim[1].SetFloat("WalkingSpeed", sp);
}
Vector3 dirToComputer = console.transform.position - npcs[1].position;
dirToComputer.y = 0;
Quaternion rot1 = Quaternion.LookRotation(dirToComputer);
npcs[1].rotation = Quaternion.Slerp(npcs[1].rotation, rot1, rotationSpeed * Time.deltaTime);
}
}
private void OnTriggerExit(Collider other)
{
if (HoriDoorManager.doorLockState == false && distance < 5f)
{
if (other.gameObject.tag == "SpaceshipCutscene")
{
FPSCamera.enabled = false;
mainCamera.enabled = true;
moveNpc = true;
anim[0].SetBool("Aiming", true);
anim[1].SetBool("Walktouse", true);
}
}
}
}
I'm calculating the distance between the player and the first npcs since I want the OnTriggerExit to trigger and work on specific direction.
When using a break point on the line:
FPSCamera.enabled = false;
It stop on this line and then I hit continue and it's getting inside the rest of the code in the Update.
But if I'm not adding a break point on that line it's not working it does nothing. Not giving errors or exception just not getting to the rest of the code in the Update.
https://docs.unity3d.com/ScriptReference/Collider.OnTriggerExit.html
OnTriggerExit occurs on the FixedUpdate after the Colliders have stopped touching
Update happens every frame, while FixedUpdate happens on a timer. So things here is probably just out of sync. Creating a break point will ensure that the frame stops and everything is probably aligned when you do that.

Collision detection script fails sometimes

For the most part this script works, however every now and then an enemy will fail at pathfinding and go through a building or wall. Is there a way i can stop this?
using UnityEngine;
using System.Collections;
namespace Daniel {
public class EnemyAI : Living {
// Detection private int range = 10; private float speed = 10f; private bool isThereAnyThing = false;
// Waypoints/Targets
public GameObject[] targets;
private float rotationSpeed = 900f;
private RaycastHit hit;
GameObject target;
[SerializeField]
private int randomTarget = 0;
[SerializeField]
float timeToNextCheck = 3;
public float effectTimer = 2f;
public GameObject deathEffect;
public LayerMask detectThis;
void Start()
{
randomTarget = Random.Range(0, 8);
target = targets[randomTarget];
}
void FixedUpdate()
{
timeToNextCheck = timeToNextCheck - Time.deltaTime;
ScanForNewWaypoint();
LookAtTarget();
Move();
CheckForObsticales();
}
void LookAtTarget()
{
//Look At Somthly Towards the Target if there is nothing in front.
if (!isThereAnyThing)
{
Vector3 relativePos = target.transform.position - transform.position;
Quaternion rotation = Quaternion.LookRotation(relativePos);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime);
}
}
void Move()
{
// Enemy translate in forward direction.
transform.Translate(Vector3.forward * Time.deltaTime * speed);
}
public void CheckForObsticales()
{
//Checking for any Obstacle in front.
// Two rays left and right to the object to detect the obstacle.
Transform leftRay = transform;
Transform rightRay = transform;
//Use Phyics.RayCast to detect the obstacle
if (Physics.Raycast(leftRay.position + (transform.right * 7f), transform.forward, out hit, range, detectThis) || Physics.Raycast(rightRay.position - (transform.right * 7f), transform.forward, out hit, range))
{
if (hit.collider.gameObject.CompareTag("Obstacles"))
{
isThereAnyThing = true;
transform.Rotate(Vector3.up * Time.deltaTime * rotationSpeed);
}
}
// Now Two More RayCast At The End of Object to detect that object has already pass the obsatacle.
// Just making this boolean variable false it means there is nothing in front of object.
if (Physics.Raycast(transform.position - (transform.forward * 4), transform.right, out hit, 10, detectThis) ||
Physics.Raycast(transform.position - (transform.forward * 4), -transform.right, out hit, 10, detectThis))
{
if (hit.collider.gameObject.CompareTag("Obstacles"))
{
isThereAnyThing = false;
}
}
}
public void ScanForNewWaypoint()
{
CheckForObsticales();
if (timeToNextCheck <= 0)
{
timeToNextCheck = Random.Range(6, 3);
randomTarget = Random.Range(0, 8);
target = targets[randomTarget];
}
}
public override void TakeHit(float dmg, Vector3 hitPoint, Vector3 hitDirection)
{
if (dmg >= health)
{
Destroy(Instantiate(deathEffect, hitPoint, Quaternion.FromToRotation(Vector3.forward, hitDirection)) as GameObject, effectTimer);
Debug.Log("Exploded");
}
base.TakeHit(dmg, hitPoint, hitDirection);
}
}
}
Okay now this is one of the most common problems people face when playing with Physics Engine and believe me there are lot of factors that adds up to the result/consequences you are facing. Most common solutions devised by people is to use Update which is Executed Every Frame for Physics calculation which is Entirely Wrong. All the physics related calculation needs to be performed inside the Fixed Update otherwise it will be too expensive to execute physics based simulations in the Update which means every single frame. In your case where your Enemy is going through walls and Physics Collisions are missing the best solution you can take is to tweak some Physics Related Properties in Unity these are located in Edit>>>Project Settings>>>Time change the Time Step and Maximum Allowed Time Step in the inspector to set your collisions right. There are some other things to keep in mind too while dealing with physics like scale, mass and colliders etc. Here is a Link concerning the detailed mechanics of the physics settings in unity. Make sure you read and understand the contents of the link before working and tweaking physics settings.

How can i make the character to start/stop walking/running slowly?

I mean that when the character is walking or running and getting to the clicked point he change the state in the animator from walk/run to idle so it looks like he walk then stop there is no animation between the walk/run and the start/stop.
I have 3 states in the animator. HumanoidWalk, HumanoidRun, HumanoidIdle.
I need something like fading.
For example if in the line:
_animator.CrossFade("Walk", 0);
I will change the 0 to 1 so when he start "Walk" it will be a bit slowly to walking speed. But in "Idle" if i will change it to 1 it will be something else not fading until he stop.
In other words i want to add fading effects when character start/stop walking/running and also when i click/double click and he switch between Walk and Run. Make some fade effects so it will not switch between the states so fast.
using UnityEngine;
using System.Collections;
public class ClickToMove : MonoBehaviour
{
public int speed = 5; // Determines how quickly object moves towards position
public float rotationSpeed = 5f;
private Vector3 targetPosition;
private Animator _animator;
private Vector3 destination;
private Quaternion targetRotation;
public float clickDelta = 0.35f; // Max between two click to be considered a double click
private bool click = false;
private float clickTime;
void Start()
{
_animator = GetComponent<Animator>();
_animator.CrossFade("Idle", 0);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
if (click && Time.time <= (clickTime + clickDelta))
{
_animator.CrossFade("Run", 0);
click = false;
}
else
{
click = true;
clickTime = Time.time;
}
_animator.CrossFade("Walk", 0);
Plane playerPlane = new Plane(Vector3.up, transform.position);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float hitdist = 0.0f;
if (playerPlane.Raycast(ray, out hitdist))
{
Vector3 targetPoint = ray.GetPoint(hitdist);
targetPosition = ray.GetPoint(hitdist);
targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
destination = targetPosition;
}
}
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, rotationSpeed);
if ((transform.position - destination).magnitude < 0.7f)
{
_animator.CrossFade("Idle", 0);
}
}
}
If you increase your transform duration value a little (like 0.25), then you can get a smooth transition between states. Also uncheck "fixed duration".

Categories

Resources