I have problem with getting two arrow key at same time, for example Up+Right for my player to move to the corner of screen, but I can have only one input at time.
So I have to check every possibility. Is there any way around?
here is my code.
void Movement()
{
// Input user, arrow keys for move left,right,up and down/////////////////////////////
if (Input.GetKey(KeyCode.LeftArrow) && transform.position.x >= -moveRangeX) //
physicPlayer.velocity = Vector2.left * moveSpeed; //
else if (Input.GetKey(KeyCode.RightArrow) && transform.position.x <= moveRangeX) //
physicPlayer.velocity = Vector2.right * moveSpeed; //
else if (Input.GetKey(KeyCode.UpArrow) && transform.position.y <= moveRangeY) //
physicPlayer.velocity = Vector2.up * moveSpeed; //
else if (Input.GetKey(KeyCode.DownArrow) && transform.position.y >= -moveRangeY) //
physicPlayer.velocity = Vector2.down * moveSpeed; //
else //
physicPlayer.velocity = Vector2.zero; //
//////////////////////////////////////////////////////////////////////////////////////
// For multiplay input user for example when user press Up+Right arrow keys.//////////////////////////////////////////////////////////////////////////////////
if (Input.GetKey(KeyCode.RightArrow) && Input.GetKey(KeyCode.UpArrow) && transform.position.x <= moveRangeX && transform.position.y <= moveRangeY) //
physicPlayer.velocity = new Vector2(1, 1) * moveSpeed; //
else if (Input.GetKey(KeyCode.RightArrow) && Input.GetKey(KeyCode.DownArrow) && transform.position.x <= moveRangeX && transform.position.y >= -moveRangeY) //
physicPlayer.velocity = new Vector2(1, -1) * moveSpeed; //
else if (Input.GetKey(KeyCode.LeftArrow) && Input.GetKey(KeyCode.DownArrow) && transform.position.x >= -moveRangeX && transform.position.y >= -moveRangeY) //
physicPlayer.velocity = new Vector2(-1, -1) * moveSpeed; //
else if (Input.GetKey(KeyCode.LeftArrow) && Input.GetKey(KeyCode.UpArrow) && transform.position.x >= -moveRangeX && transform.position.y <= moveRangeY) //
physicPlayer.velocity = new Vector2(-1, 1) * moveSpeed; //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
In your case you should remove the else if statement and put it on if statement only so your code must follow something like this :
Vector3 totalMovement = Vector3.zero;
if (Input.GetKey(KeyCode.W))
{
totalMovement += transform.forward;
}
if (Input.GetKey(KeyCode.A))
{
totalMovement -= transform.right;
}
// To ensure same speed on the diagonal, we ensure its magnitude here instead of earlier
player.MovePosition(transform.position + totalMovement.normalized * speed * Time.deltaTime);
So in your code :
if(Input.GetKey(KeyCode.RightArrow)){
physicsPlayer.velocity = new Vector2(1,1) * moveSpeed;
}
if(Input.GetKey(KeyCode.UpArrow)){
physicsPlayer.velocity = new Vector2(-1,1) * moveSpeed;
}
Something like that above.
Ps: It's untested but the logic is there . Hope it helps you :)
Here is my final edit for this code. I must use physicPlayer.velocity = new Vector2(-moveSpeed, physicPlayer.velocity.y); insted of this code physicPlayer.velocity = Vector2.left * moveSpeed;
It still got some problems but it works.
Thank you.
void Update()
{
Movement();
}
void Movement()
{
physicPlayer.velocity = Vector2.zero;
if (Input.GetKey(KeyCode.LeftArrow) && transform.position.x >= -moveRangeX)
physicPlayer.velocity = new Vector2(-moveSpeed, physicPlayer.velocity.y);
if (Input.GetKey(KeyCode.RightArrow) && transform.position.x <= moveRangeX)
physicPlayer.velocity = new Vector2(moveSpeed, physicPlayer.velocity.y);
if (Input.GetKey(KeyCode.UpArrow) && transform.position.y <= moveRangeY)
physicPlayer.velocity = new Vector2(physicPlayer.velocity.x, moveSpeed);
if (Input.GetKey(KeyCode.DownArrow) && transform.position.y >= -moveRangeY)
physicPlayer.velocity = new Vector2(physicPlayer.velocity.x, -moveSpeed);
}
Related
I make 3rd person game, where i have script for control model of my character.
Problem is that when i jump and don't push any button he stack in the air, but if i jump with pushing controlling button he worked normally.
Thanks in advance.
Player controller script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
public class RelativeMovement : MonoBehaviour
{
[SerializeField] private Transform target;
public float rotSpeed = 5.0f;
public float moveSpeed = 6.0f;
public float jumpSpeed = 15.0f;
public float gravity = -9.8f;
public float terminalVelocity = -20.0f;
public float minFall = -1.5f;
private float _vertSpeed;
private CharacterController _charController;
private ControllerColliderHit _contact;
void Start()
{
_vertSpeed = minFall;
_charController = GetComponent<CharacterController>();
}
void Update()
{
Vector3 movement = Vector3.zero;
float horInput = Input.GetAxis("Horizontal");
float vertInput = Input.GetAxis("Vertical");
if(horInput != 0 || vertInput != 0)
{
movement.x = horInput * moveSpeed;
movement.z = vertInput * moveSpeed;
movement = Vector3.ClampMagnitude(movement, moveSpeed);
Quaternion tmp = target.rotation;
target.eulerAngles = new Vector3(0, target.eulerAngles.y, 0);
movement = target.TransformDirection(movement);
target.rotation = tmp;
Quaternion direction = Quaternion.LookRotation(movement);
transform.rotation = Quaternion.Lerp(transform.rotation,
direction, rotSpeed * Time.deltaTime);
bool hitGround = false;
RaycastHit hit;
if(_vertSpeed < 0 && Physics.Raycast(transform.position, Vector3.down, out hit))
{
float check =
(_charController.height + _charController.radius) / 1.9f;
hitGround = hit.distance <= check;
}
if(hitGround)
{
if (Input.GetButtonDown("Jump"))
{
_vertSpeed = jumpSpeed;
}
else
{
_vertSpeed = minFall;
}
}
else
{
_vertSpeed += gravity * 5 * Time.deltaTime;
if(_vertSpeed < terminalVelocity)
{
_vertSpeed = terminalVelocity;
}
if(_charController.isGrounded)
{
if(Vector3.Dot(movement, _contact.normal) < 0)
{
movement = _contact.normal * moveSpeed;
}
else
{
movement += _contact.normal * moveSpeed;
}
}
}
movement.y = _vertSpeed;
movement *= Time.deltaTime;
_charController.Move(movement);
}
}
void OnControllerColliderHit(ControllerColliderHit hit)
{
_contact = hit;
}
}
Jesus photo:
enter image description here
I didn't go through all of the code but I can immediately see what can cause the problem you describe:
your entire logic happen under this if statement:
if(horInput != 0 || vertInput != 0)
So everything inside this logic block will happen only when you actively press a movement button.
You can remove it (or better yet, close the if block at the right spot.. I think it would be 2 lines down)
The answer of this question is:
if((horInput == 0 || vertInput == 0) || (horInput != 0 && vertInput != 0))
{
movement.x = horInput * moveSpeed;
movement.z = vertInput * moveSpeed;
if(horInput != 0 || vertInput != 0)
{
movement = Vector3.ClampMagnitude(movement, moveSpeed);
Quaternion tmp = target.rotation;
target.eulerAngles = new Vector3(0, target.eulerAngles.y, 0);
movement = target.TransformDirection(movement);
target.rotation = tmp;
Quaternion direction = Quaternion.LookRotation(movement);
transform.rotation = Quaternion.Lerp(transform.rotation,
direction, rotSpeed * Time.deltaTime);
}
Thanks Joe
Here is the code I m trying to edit however, the condition under the if else loops are not executing the task. In this code lanedistance is constant float variable with value 2.0f. As describe earlier it is 5lane endless runner so desired lane is considered as int variable with value 2 for middle (Ext. Left = 0, Left = 1, Middle = 2, Right = 3, Ext. Right = 4) -----------------
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.LeftArrow))
MoveLane(false);
if (Input.GetKeyDown(KeyCode.RightArrow))
MoveLane(true);
Vector3 targetposition = transform.position.z * Vector3.forward;
if (desiredLane == 0)
{
targetposition += Vector3.left * laneDistance;
}
else if (desiredLane == 1)
{
if(Input.GetKeyDown(KeyCode.LeftArrow))
{ //Debug.Log("1i condition");
MoveLane(true);
targetposition += Vector3.left * laneDistance;
}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{
//Debug.Log("1e condition");
MoveLane(false);
targetposition += Vector3.right * laneDistance;
}
}
else if (desiredLane == 3)
{
if(Input.GetKeyDown(KeyCode.LeftArrow))
{
//Debug.Log("3i condition");
MoveLane(true);
targetposition += Vector3.left * laneDistance;
}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{ //Debug.Log("3e condition");
MoveLane(true);
targetposition += Vector3.right * laneDistance;
}
}
else if (desiredLane == 4)// ----------------------
targetposition += Vector3.right * laneDistance;
Vector3 moveVector = Vector3.zero;
moveVector.x = (targetposition - transform.position).normalized.x * speed;
moveVector.y = -0.1f;
moveVector.z = speed;
controller.Move(moveVector * Time.deltaTime);
}
private void MoveLane(bool goingRight)
{
desiredLane += (goingRight) ? 5 : -1;// ------------------
desiredLane = Mathf.Clamp(desiredLane, 0, 4);// ------------------
Debug.Log("Value is: "+desiredLane);
}
}
I guess your code can be simplified a lot.
Also why would you handle the first two GetKeyDown statements always without any check at all? And what happened to the case where desiredLane == 2?
And why do you use
desiredLane += (goingRight) ? 5 : -1
it should probably rather be
desiredLane += (goingRight) ? 1 : -1
I'd say you rather want to do something like
// Configure these two vis the Inspector!
public float sidewardsSpeed;
public float forwardSpeed;
// Not necessary but this way you can give your checks handy names
private bool CanMoveLeft => desiredLane > 0;
private bool CanMoveRight => desiredLane < 4;
float targetPositionX;
void Start()
{
targetPositionX = transform.position.x;
}
void Update()
{
// This is for the sidewards movement
// It's enough to simply check the value of your index ONCE instead of
// covering each possible case ;)
if (CanMoveLeft && Input.GetKeyDown(KeyCode.LeftArrow))
MoveLane(false);
else if (CanMoveRight && Input.GetKeyDown(KeyCode.RightArrow))
MoveLane(true);
// Finally calculate a smoothed movement on the individual axes
var currentPosition = transform.position;
var deltaX = targetPositionX - currentPosition.x;
var x = Mathf.Min(deltaX, Mathf.Sign(deltaX) * sidewardsSpeed * Time.deltaTime);
var y = -0.1f * Time.deltaTime;
var z = forwardSpeed * Time.deltaTime;
// And then apply both movements
controller.Move(new Vector3(x, y, z));
}
private void MoveLane(bool goingRight)
{
var direction = goingRight ? 1 : -1;
desiredLane += direction;
desiredLane = Mathf.Clamp(desiredLane, 0, 4);
Debug.Log("Value is: "+desiredLane);
// Also directly calculate the target X position
targetPositionX = (desiredLane - 2) * laneDistance;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Follow : MonoBehaviour
{
public Transform targetToFollow;
public Text text;
public float lookAtRotationSpeed;
public float moveSpeed;
private float minMoveSpeed = 0f;
private bool moveInDistance = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void FixedUpdate()
{
Vector3 lTargetDir = targetToFollow.position - transform.position;
lTargetDir.y = 0.0f;
transform.rotation = Quaternion.RotateTowards(transform.rotation,
Quaternion.LookRotation(lTargetDir), Time.time * lookAtRotationSpeed);
var distance = Vector3.Distance(transform.position, targetToFollow.position);
text.text = distance.ToString();
if(distance > 5f && moveInDistance == false)
{
moveSpeed = moveSpeed + 0.5f * Time.deltaTime;
}
if (distance > 1.5f && distance < 5f)
{
moveInDistance = true;
moveSpeed = moveSpeed + 0.05f;
}
else if (distance < 1f)
{
moveSpeed = Mathf.Max(minMoveSpeed, moveSpeed - 0.3f);
}
transform.position = Vector3.MoveTowards(transform.position, targetToFollow.position, Time.deltaTime * moveSpeed);
}
}
The first time the game is running the transform will move faster to the target in this part :
if(distance > 5f && moveInDistance == false)
{
moveSpeed = moveSpeed + 0.5f * Time.deltaTime;
}
Then when the transform has reach close distance to the target he will keep following the target in slower speed in this part :
if (distance > 1.5f && distance < 5f)
{
moveInDistance = true;
moveSpeed = moveSpeed + 0.05f;
}
The problem is if in the future in the game I will want to change the speed again if the transform will be more then 5 distance from the target. Then where should I change the flag moveInDistance to false again ?
You can put moveInDistance before moving logical like
moveInDistance = distance > 1.5f && distance < 5f; // or other condition
if(distance > 5f && !moveInDistance)
{
moveSpeed = moveSpeed + 0.5f * Time.deltaTime;
}
if (distance > 1.5f && distance < 5f)
{
moveSpeed = moveSpeed + 0.05f;
}
else if (distance < 1f)
{
moveSpeed = Mathf.Max(minMoveSpeed, moveSpeed - 0.3f);
}
...
Add example if else for comment
...
float ms = moveSpeed;
if(distance > 5f)
{
ms = moveSpeed + 0.5f; //move faster
}
else if (distance < 1f)
{
ms = Mathf.Max(minMoveSpeed, moveSpeed - 0.3f); // move slower
}else {
//set your ms (movement speed) when follwer is move in distance range if you don’t need default value that equal moveSpeed here
}
// by default if distance in range of 1-5 ms is equal moveSpeed and IsInRange Case
// move object by using ms value
...
Ps. In my opinion I think moveInDistance is not important thing to use in my if-else condition you can check distance range in elseIf statement instead of set to moveInDistance
You could edit your existing if statement alittle to include what you are after:
if(distance > 5f)
{
if (moveInDistance == false) {
moveSpeed = moveSpeed + 0.5f * Time.deltaTime;
} else {
moveInDistance = false;
}
}
Having a bit of a problem in Unity3D. I have a fly camera with both a box collider and rigidbody, and it still moves through my terrain, which has a terrain collider and a rigidbody. The thing is, it interacts with my capsules just fine, bounces them away and everything. Obvious this is the exact opposite of what I want ha ha...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlyCamera : MonoBehaviour
{.
/*
Writen by Windexglow 11-13-10. Use it, edit it, steal it I don't care.
Converted to C# 27-02-13 - no credit wanted.
Simple flycam I made, since I couldn't find any others made public.
Made simple to use (drag and drop, done) for regular keyboard layout
wasd : basic movement
shift : Makes camera accelerate
space : Moves camera on X and Z axis only. So camera doesn't gain any height*/
float mainSpeed = 25.0f; //regular speed
float shiftAdd = 250.0f; //multiplied by how long shift is held. Basically running
float maxShift = 1000.0f; //Maximum speed when holdin gshift
float camSens = 0.25f; //How sensitive it with mouse
private Vector3 lastMouse = new Vector3(255, 255, 255); //kind of in the middle of the screen, rather than at the top (play)
private float totalRun = 1.0f;
void Update()
{
if (Input.GetKey(KeyCode.R))
{
transform.position = new Vector3(26f, 4f, 14f);
}
lastMouse = Input.mousePosition - lastMouse;
lastMouse = new Vector3(-lastMouse.y * camSens, lastMouse.x * camSens, 0);
lastMouse = new Vector3(transform.eulerAngles.x + lastMouse.x, transform.eulerAngles.y + lastMouse.y, 0);
transform.eulerAngles = lastMouse;
lastMouse = Input.mousePosition;
//Mouse camera angle done.
//Keyboard commands
float f = 0.0f;
Vector3 p = GetBaseInput();
if (Input.GetKey(KeyCode.LeftShift))
{
totalRun += Time.deltaTime;
p = p * totalRun * shiftAdd;
p.x = Mathf.Clamp(p.x, -maxShift, maxShift);
p.y = Mathf.Clamp(p.y, -maxShift, maxShift);
p.z = Mathf.Clamp(p.z, -maxShift, maxShift);
}
else
{
totalRun = Mathf.Clamp(totalRun * 0.5f, 1f, 1000f);
p = p * mainSpeed;
}
p = p * Time.deltaTime;
Vector3 newPosition = transform.position;
if (Input.GetKey(KeyCode.Space))
{ //If player wants to move on X and Z axis only
transform.Translate(p);
newPosition.x = transform.position.x;
newPosition.z = transform.position.z;
transform.position = newPosition;
}
else
{
transform.Translate(p);
}
}
private Vector3 GetBaseInput()
{ //returns the basic values, if it's 0 than it's not active.
Vector3 p_Velocity = new Vector3();
if (Input.GetKey(KeyCode.W))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(0, 0, 1);
}
}
}
}
if (Input.GetKey(KeyCode.S))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(0, 0, -1);
}
}
}
}
if (Input.GetKey(KeyCode.A))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(-1, 0, 0);
}
}
}
}
if (Input.GetKey(KeyCode.D))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(1, 0, 0);
}
}
}
}
return p_Velocity;
}
}
This flycam isn't mine so if it's not optimal for the use I'm looking for, please notify me about that too.
Basically you are. Transforming it not adding velocity thats why it is crossing the collider
You need to get reference of the rigidbody then add velocity to it
Then it won't cross the collider
You need to modify your code for that
Where you are transforming
Instead of transforming
You need to
Rigidbody.velocity= vector3(.....)
Never mind, I fixed the problem.
I ended up having Kinematic ticked on the box collider of the camera, so that must have messed it up.
I'm trying to make my character idle, run, jump and fall. I did it, but i have bug with runing animation. While he goes left or right, he doesn't play animation "run", which called by integer "noob" with parameter "2",he plays animation "fall", which "noob" is parameter "4"
I'm using Unity 4.5.x and C# code
using UnityEngine;
using System.Collections;
public class movement : MonoBehaviour {
Rigidbody2D rb;
Animator anim;
public int jumpCount = 0;
public Camera main;
float jumpTimer = 0;
void Start () {
rb = GetComponent<Rigidbody2D> ();
anim = GetComponent<Animator>();
}
void Update () {
if (Input.GetKeyDown (KeyCode.X) && jumpCount < 2 && jumpTimer == 0) {
jump ();
jumpCount += 1;
jumpTimer = 1;
StartCoroutine("jumpTime");
}
if (rb.velocity.y > 0) {
Flip();
anim.SetInteger ("noob", 3);
}
if (rb.velocity.y < 0) {
Flip();
anim.SetInteger ("noob", 4);
}
if (Input.GetAxis ("Horizontal") == 0 && rb.velocity.y == 0) {
anim.SetInteger ("noob", 1);
}
if (rb.velocity.y == 0 && Input.GetAxis ("Horizontal") != 0) {
Flip();
anim.SetInteger("noob", 2);
}
if (rb.velocity.y == 0) {
jumpCount = 0;
}
}
void FixedUpdate(){
rb.velocity = new Vector2 (Input.GetAxis ("Horizontal") * 12f, rb.velocity.y);
}
void jump(){
rb.AddForce (transform.up * 14F, ForceMode2D.Impulse);
}
void Flip() {
if (Input.GetAxis ("Horizontal") > 0) {
transform.localRotation = Quaternion.Euler (0, 0, 0);
}
if (Input.GetAxis ("Horizontal") < 0) {
transform.localRotation = Quaternion.Euler (0, 180, 0);
}
}
IEnumerator jumpTime() {
yield return new WaitForSeconds (0.4f);
jumpTimer = 0;
}
}
I tried to do something with jumCount, jumpTimer and velocity.y, but nothing helped
I would suggested making a grounded and jumping bool, you can use this bool to determine whether your character is airbourne. Also using else if conditional statements may help here to avoid setting your value more than once. Then you can do something like this:
if (grounded && jumping) {
Flip();
anim.SetInteger ("noob", 3);
jumping = false;
}
else if (!grounded) {
Flip();
anim.SetInteger ("noob", 4);
}
else if (Input.GetAxis ("Horizontal") == 0 && grounded) {
anim.SetInteger ("noob", 1);
}
else if (grounded && Input.GetAxis ("Horizontal") != 0) {
Flip();
anim.SetInteger("noob", 2);
}