I want to make my character to move smoothly when I tilt my phone. How I can make it to move smoothly and the velocity and the speed increases as the slope of the phone?
void AccelerometerMove()
{
float x = Input.acceleration.x;
Debug.Log("X = " + x);
if (x < -0.1f)
{
MoveLeft();
}
else if (x > 0.1f)
{
MoveRight();
}
else
{
SetVelocityZero();
}
}
public void SetVelocityZero()
{
rb.velocity = Vector2.zero;
}
public void MoveLeft()
{
rb.velocity = new Vector2(-speed, 0);
//transform.Translate(Vector2.right * speed * Time.deltaTime);
transform.eulerAngles = new Vector2(0, 180);
}
public void MoveRight()
{
rb.velocity = new Vector2(speed, 0);
//transform.Translate(Vector2.right * speed * Time.deltaTime);
transform.eulerAngles = new Vector2(0, 0);
}
Check out this answer about using a moving average/low-pass filter here
You could achieve a similar effect by using the Vector3.Lerp function.
Related
I only recently got into Unity, and I have made a character movement system; everything is working besides from sprinting. I have the user use "Left Shift" to sprint, although it seems sprinting never turns off. I'm not quite sure the reasoning as to why this happens or what part of code could be fixed to accommodate for this, as such, I have attached the source file of movement.
Here is the paste: https://pastebin.com/S1h5pEwq
In particular, this is the movement function:
void Movement()
{
Vector2 axis = new Vector2(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal")) * walkSpeed;
Vector3 forward = new Vector3(-Camera.main.transform.right.z, 0.0f, Camera.main.transform.right.x);
Vector3 wishDirection = (forward * axis.x + Camera.main.transform.right * axis.y + Vector3.up * rb.velocity.y);
rb.velocity = wishDirection;
if (Input.GetKey(KeyCode.LeftShift))
{
isSprinting = true;
}
else
{
isSprinting = false;
}
if (isSprinting == true)
{
walkSpeed = 10.0f;
}
}
More specifically, my goal is to have Sprint be activated strictly while the key is pressed.
Try this:
void Movement()
{
Vector2 axis = new Vector2(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal")) * walkSpeed;
Vector3 forward = new Vector3(-Camera.main.transform.right.z, 0.0f, Camera.main.transform.right.x);
Vector3 wishDirection = (forward * axis.x + Camera.main.transform.right * axis.y + Vector3.up * rb.velocity.y);
rb.velocity = wishDirection;
if (Input.GetKey(KeyCode.LeftShift))
{
isSprinting = true;
}
else
{
isSprinting = false;
}
if (isSprinting == true)
{
walkSpeed = 10.0f;
}
else
{
walkSpeed = 0.0f
}
}
The problem in your script was that you were not resetting the speed.
If(Input.GetKeyUp(KeyCode.LeftShift)){
isSprinting = false;
}
This will do, you didn't check when the player stopped pressing shift.
I have a 3D object that I want to rotate with mouse/finger swipe, so I made the script below.
The object's rotation looks smooth on editor, but when playing the game on real device (android), the rotation didn't follow the finger movement immediately, it takes some milliseconds to follow finger, it isn't smooth and the controls become hard and frustrating!
float sensitivity = 0.8f;
Vector2 firstPressPos;
Vector2 secondPressPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
//save began touch 2d point
firstPressPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y);
}
if (Input.GetMouseButton(0))
{
//save ended touch 2d point
secondPressPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y);
if (firstPressPos != secondPressPos)
{
float RotX = Input.GetAxis("Mouse X") * sensitivity * Time.deltaTime;
float RotY = Input.GetAxis("Mouse Y") * sensitivity * Time.deltaTime;
transform.RotateAround(Vector3.up, RotX);
transform.RotateAround(Vector3.right, -RotY);
}
}
}
try this code
// Screen Touches
Vector2?[] oldTouchPositions = {
null,
null
};
// Rotation Speed
public float rotSpeed = 0.5f;
public void Update()
{
if (Input.touchCount == 0)
{
oldTouchPositions[0] = null;
oldTouchPositions[1] = null;
}
else if (Input.touchCount == 1)
{
if (oldTouchPositions[0] == null || oldTouchPositions[1] != null)
{
oldTouchPositions[0] = Input.GetTouch(0).position;
oldTouchPositions[1] = null;
}
else
{
Vector2 newTouchPosition = Input.GetTouch(0).position;
float distanceX = (oldTouchPositions[0] - newTouchPosition).Value.x;
float distanceY = (oldTouchPositions[0] - newTouchPosition).Value.y;
float rotX = distanceX * rotSpeed * Mathf.Deg2Rad;
float rotY = distanceY * rotSpeed * Mathf.Deg2Rad;
transform.Rotate(Vector3.up, rotX * 5, Space.Self);
transform.Rotate(Vector3.left, rotY * 5, Space.Self);
oldTouchPositions[0] = newTouchPosition;
}
}
else
{
if (oldTouchPositions[1] == null)
{
oldTouchPositions[0] = Input.GetTouch(0).position;
oldTouchPositions[1] = Input.GetTouch(1).position;
}
else
{
}
}
}
Here's a script I found a few years back that manipulates X axis spin with Mouse or Touches. It seems to work well with touches, but not as good with Mouse. Try it and let me know if it behaves a bit better. This one should adjust the spinning speed dynamically:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpinDrag : MonoBehaviour {
float f_lastX = 0.0f;
float f_difX = 0.5f;
float f_steps = 0.0f;
int i_direction = 1;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
f_difX = 0.0f;
}
else if (Input.GetMouseButton(0))
{
f_difX = Mathf.Abs(f_lastX - Input.GetAxis("Mouse X"));
if (f_lastX < Input.GetAxis("Mouse X"))
{
i_direction = -1;
transform.Rotate(Vector3.up, -f_difX);
}
if (f_lastX > Input.GetAxis("Mouse X"))
{
i_direction = 1;
transform.Rotate(Vector3.up, f_difX);
}
f_lastX = -Input.GetAxis("Mouse X");
}
else
{
if (f_difX > 0.5f) f_difX -= 0.05f;
if (f_difX < 0.5f) f_difX += 0.05f;
transform.Rotate(Vector3.up, f_difX * i_direction);
}
}
}
So basically I am trying to make player movement system like one in RPG Maker with 8 directions. Somehow I succeded, but only partially. When I am trying to suddenly change direction for ex. from up to left, character stutter and do not want to move without releasing all keys first.
Gravity scale is disabled or more like set to 0, body type is dynamic.
Here is a code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveChar : MonoBehaviour {
Rigidbody2D rigid;
public float Speed;
// Use this for initialization
void Start () {
rigid = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update () {
// float horiz = Input.GetAxis("Horizontal");
// float vert = Input.GetAxis("Vertical");
if(Input.GetKeyDown(KeyCode.W)) //________________________________________MOVING UP
{
rigid.velocity = new Vector2(rigid.velocity.x, 1 * Speed);
}
else if(Input.GetKeyUp(KeyCode.W))
{
rigid.velocity = new Vector2(0, 0);
}
if (Input.GetKeyDown(KeyCode.S)) //_______________________________________MOVING DOWN
{
rigid.velocity = new Vector2(rigid.velocity.x, -1 * Speed);
}
else if (Input.GetKeyUp(KeyCode.S))
{
rigid.velocity = new Vector2(0, 0);
}
if (Input.GetKeyDown(KeyCode.A)) //_______________________________________MOVING LEFT
{
rigid.velocity = new Vector2(-1 * Speed, rigid.velocity.y);
}
else if (Input.GetKeyUp(KeyCode.A))
{
rigid.velocity = new Vector2(0, 0);
}
if (Input.GetKeyDown(KeyCode.D)) //_______________________________________MOVING RIGHT
{
rigid.velocity = new Vector2(1 * Speed, rigid.velocity.y);
}
else if (Input.GetKeyUp(KeyCode.D))
{
rigid.velocity = new Vector2(0, 0);
}
}
Use Input.GetAxis(axisName) to avoid conflicting cases in your input code. Also, use AddForce to play nicely with other rigidbodies.
Vector2 oldV = rigid.velocity;
float horiz = Input.GetAxis("Horizontal");
float vert = Input.GetAxis("Vertical");
Vector2 newV = new Vector2(horiz * Speed, vert * Speed);
rigid.AddForce(newV-oldV, ForceMode2D.Impulse);
Alternatively, keep track of your own axes when keys are lifted/pressed down
public float horiz;
public float vert;
void Start() {
horiz = 0f;
vert = 0f;
if (Input.GetKey(KeyCode.A)) horiz -= 1f;
if (Input.GetKey(KeyCode.D)) horiz += 1f;
if (Input.GetKey(KeyCode.S)) vert -= 1f;
if (Input.GetKey(KeyCode.W)) vert += 1f;
}
void Update () {
Vector2 oldV = rigid.velocity;
if(Input.GetKeyDown(KeyCode.W)) vert += 1f;
else if(Input.GetKeyUp(KeyCode.W)) vert -= 1f;
if (Input.GetKeyDown(KeyCode.S)) vert -= 1f;
else if (Input.GetKeyUp(KeyCode.S)) vert += 1f;
if (Input.GetKeyDown(KeyCode.A)) horiz -= 1f;
else if (Input.GetKeyUp(KeyCode.A)) horiz += 1f;
if (Input.GetKeyDown(KeyCode.D)) horiz += 1f;
else if (Input.GetKeyUp(KeyCode.D)) horiz -= 1f;
Vector2 newV = new Vector2(horiz * Speed, vert * Speed);
rigid.AddForce(newV-oldV, ForceMode2D.Impulse);
}
There is only a small problem with releasing the button. Add the original force in the direction that is not affected by the key. The whole script should look like this:
void Update()
{
if (Input.GetKeyDown(KeyCode.W)) //________________________________________MOVING UP
{
rigid.velocity = new Vector2(rigid.velocity.x, 1 * Speed);
}
else if (Input.GetKeyUp(KeyCode.W))
{
rigid.velocity = new Vector2(rigid.velocity.x, 0);
}
if (Input.GetKeyDown(KeyCode.S)) //_______________________________________MOVING DOWN
{
rigid.velocity = new Vector2(rigid.velocity.x, -1 * Speed);
}
else if (Input.GetKeyUp(KeyCode.S))
{
rigid.velocity = new Vector2(rigid.velocity.x, 0);
}
if (Input.GetKeyDown(KeyCode.A)) //_______________________________________MOVING LEFT
{
rigid.velocity = new Vector2(-1 * Speed, rigid.velocity.y);
}
else if (Input.GetKeyUp(KeyCode.A))
{
rigid.velocity = new Vector2(0, rigid.velocity.y);
}
if (Input.GetKeyDown(KeyCode.D)) //_______________________________________MOVING RIGHT
{
rigid.velocity = new Vector2(1 * Speed, rigid.velocity.y);
}
else if (Input.GetKeyUp(KeyCode.D))
{
rigid.velocity = new Vector2(0, rigid.velocity.y);
}
}
I hope this helps you.
Now all the objects are moving at the same speed using moveSpeed global variable.
private void MoveToNextFormation()
{
float step = moveSpeed * Time.deltaTime;
for (int i = 0; i < squadMembers.Count; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
if (randomSpeed == true)
{
step = Random.Range(3, 50) * Time.deltaTime;
}
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
if (Vector3.Distance(squadMembers[i].transform.position, newpos[i]) < threshold)
{
if (squareFormation == true)
{
Vector3 degrees = new Vector3(0, -90f, 0);
Quaternion quaternion = Quaternion.Euler(degrees);
squadMembers[i].transform.rotation = Quaternion.Slerp(squadMembers[i].transform.rotation, quaternion, rotateSpeed * Time.deltaTime);
}
else
{
squadMembers[i].transform.rotation = Quaternion.Slerp(squadMembers[i].transform.rotation, qua[i], rotateSpeed * Time.deltaTime);
}
}
}
}
I tried to add this part:
if (randomSpeed == true)
{
step = Random.Range(3, 50) * Time.deltaTime;
}
But it's not effecting on the speed movement.
I want each character to move in another speed.
Have a simple AI thats follows the player when in range and randomly moves the ai around when it's not in the player range. When the AI hits a wall and is out of the players range it starts to spin all the time. Can't work out why it keeps doing so.
I may be missing a simple thing...
Many thanks for any help.
void Update()
{
Target = GameObject.FindGameObjectWithTag("Player");
if (Vector3.Distance(Target.transform.position, transform.position) < 25)
{
followPlayer();
}
else
{
randomMovement();
}
}
public void followPlayer()
{
if (Vector3.Distance(transform.position, Target.transform.position) >= MinDist)
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
transform.LookAt(Target.transform);
if (Vector3.Distance(transform.position, Target.transform.position) <= MaxDist)
{
}
}
else
{
}
}
public void randomMovement()
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
transform.Rotate(RandomDirection * Time.deltaTime * 10.0f);
}
void OnCollisionEnter(Collision col)
{
bool hasTurned = false;
if (col.transform.gameObject.name != "Terrain")
{
if(hasTurned == false)
{
RandomDirection = new Vector3(0, Mathf.Sin(TimeBetween) * (RotationRange / 2) + OriginalDirection, 0);
randomMovement();
hasTurned = true;
}
else
{
randomMovement();
hasTurned = false;
}
Debug.Log("Hit");
}
The reason it is continuously spinning is because you are continuously calling randomMovement() in your Update() which continously applies a rotation to your object with Rotate(). It sounds like what you are instead trying to do is have the object wander aimlessly every few seconds. You could do this by implementing on timer on your randomMovement() so that every few seconds, it generates a new rotation(similar to what you have in the onCollision). Example below.
float t = 0;
public void randomMovement()
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
t += Time.deltaTime;
if (t > 3f) // set to a new rotation every 3 seconds.
{
t = 0; // reset timer
RandomDirection = new Vector3(0, Random.Range(0f, 360f), 0); // turn towards random direction
transform.Rotate(RandomDirection);
}
}