I have a working player movement script that I made from the free character controller 2D asset script and my own, it works using the A and D keys of the keyboard, for moving left and right.
I want to have this code work for touchscreen mobile phones. Basically, you press the left side of the screen to move left, the right side for right.
I'm still new to C# and can use the help.
Here's my current playermovement script.
Thanks in advance!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f;
private Rigidbody2D m_Rigidbody2D;
private Vector3 m_Velocity = Vector3.zero;
public float runSpeed = 40f;
float horizontalMove = 0f;
private void Awake()
{
m_Rigidbody2D = GetComponent<Rigidbody2D>();
}
public void Move(float move)
{
// Move the character by finding the target velocity
Vector3 targetVelocity = new Vector2(move * 10f,
m_Rigidbody2D.velocity.y);
// And then smoothing it out and applying it to the character
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity,
targetVelocity, ref m_Velocity, m_MovementSmoothing);
}
// Update is called once per frame
void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed;
}
void FixedUpdate()
{
// Move our character
Move(horizontalMove * Time.fixedDeltaTime);
}
}
There are several solutions to this but one solution could be to use the Input API to get touches:
void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed;
for (int i = 0; i < Input.touchCount; ++i)
{
Touch touch = Input.GetTouch(i);
bool touchIsOnRightSide = touch.position.x > Screen.width / 2;
horizontalMove.x = runSpeed;
if (!touchIsOnRightSide)
horizontalMove.x *= -1;
}
}
In this code we will loop through all touches and check if they're on the right or left side by checking if the X coordinates of the touch is bigger or smaller than the X coordinates in the middle of the screen and then apply movement in that direction.
Related
I've been recently working on a project using Unity Engine that involves a sort of Top-Down, 3rd person view, and I have been having trouble with the character movement.
I want to implement a way for the player to move throughout the map using either WASD movement, Click-to-Move movement, or Drag-to-Move movement, allowing them to use either of these freely and at any time, yet I have not yet found a way of doing this, since the methods end up cancelling each other out, leading the Player Character to awkward movement and to getting stuck in place.
Is there any way of achieving this? If so, any tips/suggestions would be greatly appreciated. Please keep in mind I am a complete beginner when it comes to both Unity and C#, so I might not grasp some core concepts yet.
I have attached my PlayerMovement C# code below.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(test))]
public class PlayerMovement : MonoBehaviour
{
private test _input;
//click2move
private NavMeshAgent agent;
//x
[SerializeField]
private bool RotateTowardMouse;
[SerializeField]
private float MovementSpeed;
[SerializeField]
private float RotationSpeed;
[SerializeField]
private Camera Camera;
void Start()
{
//c2m
agent = GetComponent<NavMeshAgent>();
//x
}
private void Awake()
{
_input = GetComponent<test>();
}
// Update is called once per frame
void Update()
{
var targetVector = new Vector3(_input.InputVector.x, 0, _input.InputVector.y);
var movementVector = MoveTowardTarget(targetVector);
agent.autoBraking = true;
if (!RotateTowardMouse)
{
RotateTowardMovementVector(movementVector);
}
if (RotateTowardMouse)
{
RotateFromMouseVector();
}
//c2m
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (Input.GetMouseButtonDown(0))
{
agent.SetDestination(hit.point);
}
}
else
{
if (agent.remainingDistance < 1)
{
agent.ResetPath();
}
}
}
private void RotateFromMouseVector()
{
Ray ray = Camera.ScreenPointToRay(_input.MousePosition);
if (Physics.Raycast(ray, out RaycastHit hitInfo, maxDistance: 300f))
{
var target = hitInfo.point;
target.y = transform.position.y;
transform.LookAt(target);
}
}
private Vector3 MoveTowardTarget(Vector3 targetVector)
{
var speed = MovementSpeed * Time.deltaTime;
// transform.Translate(targetVector * (MovementSpeed * Time.deltaTime)); Demonstrate why this doesn't work
//transform.Translate(targetVector * (MovementSpeed * Time.deltaTime), Camera.gameObject.transform);
targetVector = Quaternion.Euler(0, Camera.gameObject.transform.rotation.eulerAngles.y, 0) * targetVector;
var targetPosition = transform.position + targetVector * speed;
transform.position = targetPosition;
return targetVector;
}
private void RotateTowardMovementVector(Vector3 movementDirection)
{
if (movementDirection.magnitude == 0) { return; }
var rotation = Quaternion.LookRotation(movementDirection);
transform.rotation = Quaternion.RotateTowards(transform.rotation, rotation, RotationSpeed);
}
}
I would highly recommend that you use the Unity Input System. It can automate switching between input devices and decouple your code from any specific controls. It might be a bit overwhelming if you have limited experience with C#, but there is a vast library of tutorial videos and written guides you can rely on.
The PlayerInput component is what detects when different input devices are added or removed and switches to the first valid control scheme. When a user activates the inputs required to trigger something in your game, that is represented as an Action. A set of callbacks for that action are called depending on the states of the input: started, performed, and canceled. These are where you hook up your character controller to the input and run any extra logic necessary to turn an input into movement. The Input System also has a feature called interactions that will probably be useful, especially for drag-to-move controls.
Good luck! If you'd like me to explain something further or point you to a good tutorial, feel free to tag me in a comment.
First create a Capsule in the scene, drag the main camera to its object, hang the script under the Capsule object, WASD controls the movement direction, the space moves up along the Y axis, and the F moves down along the Y axis, thank you
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCam : MonoBehaviour
{
private Vector3 m_camRot;
private Transform m_camTransform;//Camera Transform
private Transform m_transform;//Camera parent object Transform
public float m_movSpeed=10;//Movement factor
public float m_rotateSpeed=1;//Rotation factor
private void Start()
{
m_camTransform = Camera.main.transform;
m_transform = GetComponent<Transform>();
}
private void Update()
{
Control();
}
void Control()
{
if (Input.GetMouseButton(0))
{
//Get the mouse movement distance
float rh = Input.GetAxis("Mouse X");
float rv = Input.GetAxis("Mouse Y");
// rotate the camera
m_camRot.x -= rv * m_rotateSpeed;
m_camRot.y += rh*m_rotateSpeed;
}
m_camTransform.eulerAngles = m_camRot;
// Make the main character face in the same direction as the camera
Vector3 camrot = m_camTransform.eulerAngles;
camrot.x = 0; camrot.z = 0;
m_transform.eulerAngles = camrot;
// Define 3 values to control movement
float xm = 0, ym = 0, zm = 0;
//Press W on the keyboard to move up
if (Input.GetKey(KeyCode.W))
{
zm += m_movSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.S))//Press keyboard S to move down
{
zm -= m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.A))//Press keyboard A to move left
{
xm -= m_movSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.D))//Press keyboard D to move right
{
xm += m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.Space) && m_transform.position.y <= 3)
{
ym+=m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.F) && m_transform.position.y >= 1)
{
ym -= m_movSpeed * Time.deltaTime;
}
m_transform.Translate(new Vector3(xm,ym,zm),Space.Self);
}
}
I'm writing a 2D platform game with Visual Studio Code and Unity. So far, I have established the animations that I will use later in the main character and the enemy. With the main character I have defined the "horizontal move" and the "vertical move". However when I run the game, the character moves up, but it doesn't move left or right.
This is the code that I have for the main character:
public class Hero : Monobehaviour
{
public float vel =10f;
public Animator anim;
private Vector2 moveVelocity;
float horizontalMove = 0f;
private Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * vel;
Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
moveVelocity = moveInput.normalized * vel;
}
void FixedUpdate()
{
Vector2 v = new Vector2 (vel, 0);
rb.velocity = v;
rb.MovePosition(rb.position + moveVelocity * Time.fixedDeltaTime);
}
}
Can someone please tell me what I'm missing?
It should work if you change your code to this:
void Update()
{
if(Input.GetKeyDown(KeyCode.D))
{
rb.AddRelativeForce(Vector2.right * (vel*Time.deltaTime));
}
else if(Input.GetKeyDown(KeyCode.A))
{
rb.AddRelativeForce(Vector2.left * (vel*Time.deltaTime));
}
}
Since you have a rigidbody attached to your game object, it would make sense to add relative force to the object when a user presses D/A instead of just changing the object's transform position. This should work.
Essentially, you can set the horizontal move up in the input manager under Edit > project settings > input. Double-check if the horizontal axis is set up to the left and right button.
So there is the code with my Character's Rigidbody2D attachment, but he does not move when is set to Kinematic (working only on Dynamic), but I want Kinematic because he collides with Dynamic Objects and i didn't want him to move just left and right on touch.
UI: I'm very beginner, I just want to make my first game for Android and sorry for my english too. :D
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
//variables
public float moveSpeed = 300;
public GameObject character;
private Rigidbody2D characterBody;
private float ScreenWidth;
// Use this for initialization
void Start()
{
ScreenWidth = Screen.width;
characterBody = character.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
int i = 0;
//loop over every touch found
while (i < Input.touchCount)
{
if (Input.GetTouch(i).position.x > ScreenWidth / 2)
{
//move right
RunCharacter(1.0f);
}
if (Input.GetTouch(i).position.x < ScreenWidth / 2)
{
//move left
RunCharacter(-1.0f);
}
++i;
}
}
void FixedUpdate()
{
#if UNITY_EDITOR
RunCharacter(Input.GetAxis("Horizontal"));
#endif
}
private void RunCharacter(float horizontalInput)
{
//move player
characterBody.AddForce(new Vector2(horizontalInput * moveSpeed * Time.deltaTime, 0));
}
}
From Unity docs,
If isKinematic is enabled, Forces, collisions or joints will not affect the rigidbody anymore.
So instead of applying a force, just change it's position. Something like this:
private void RunCharacter(float horizontalInput)
{
//move player
characterBody.transform.position += new Vector2(horizontalInput * moveSpeed * Time.deltaTime, 0);
}
I'm currently developing an FPS shooter in Unity 3D. I'm fairly new to Unity and I've been having a bit of trouble with my player movement script. Individually everything seems to work, I can rotate and move the player freely, however when I try doing the two simultaneously my player seems to lock and won't rotate.
Sometimes jumping or moving to higher ground on the terrain seems to fix the issue, however I ran a few checks with gravity disabled, no colliders, and with the player well above ground, so the problem seems to be with the script. I've also done a bit of debugging and the Rotate() code does run, just the rotation amount doesn't seem to change.
Here is the player movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerMov : MonoBehaviour
{
[SerializeField]
private Camera cam;
[SerializeField]
private float speed = 5f;
[SerializeField]
private float looksensitivity = 4f;
[Header("Camera View Lock:")]
[SerializeField] //min and max amount for looking up and down (degrees)
private float lowlock = 70f;
[SerializeField]
private float highlock = 85f;
private Rigidbody rb;
private float currentrotx; //used later for calculating relative rotation
public Vector3 velocity;
public Vector3 rotation; // rotates the player from side to side
public float camrotation; // rotates the camera up and down
public float jmpspe = 2000f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
CalcMovement();
CalcRotation();
Rotate();
}
void FixedUpdate()
{
Move();
}
private void CalcRotation()
{
float yrot = Input.GetAxisRaw("Mouse X"); //around x axis
rotation = new Vector3(0f, yrot, 0f) * looksensitivity;
float xrot = Input.GetAxisRaw("Mouse Y"); //around y axis
camrotation = xrot * looksensitivity;
}
private void CalcMovement()
{
float xmov = Input.GetAxisRaw("Horizontal");
float zmov = Input.GetAxisRaw("Vertical");
Vector3 movhor = transform.right * xmov;
Vector3 movver = transform.forward * zmov;
velocity = (movhor + movver).normalized * speed;
}
void Move()
{
//move
if (velocity != Vector3.zero)
{
rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);
}
//jump
if (Input.GetKeyDown(KeyCode.Space))
{
//add double jump limit later!
rb.AddForce(0, jmpspe * Time.deltaTime, 0, ForceMode.Impulse);
}
}
void Rotate()
{
//looking side to side
rb.MoveRotation(rb.rotation * Quaternion.Euler(rotation));
// camera looking up and down
currentrotx -= camrotation;
currentrotx = Mathf.Clamp(currentrotx, -lowlock, highlock);
cam.transform.localEulerAngles = new Vector3(currentrotx, 0, 0);
}
}
Here are the relevant components attached to my player:
(The player has a couple more components attached but I ran tests without them and the problem still occurs)
Like I said I'm a bit of a unity novice, so i'm sure I missed something small but I just can't seem to place my finger on it, I've been stuck on this for a while so any help is much appreciated.
SOLVED:
It seems the problem I had was because I was running the scene from my laptop and not a desktop which I assume is what the Unity input was built for.
I am creating a 2D side-scroller video game in Unity using c#. I have created the script that makes the player face the direction that the arrow key that was pressed was pointing to (when the right arrow is pressed, the player faces right. When the left arrow is pressed, the player faces left).
However, I cannot figure out how to make the harpoon that the player shoots point in the direction the player is facing. I have found many questions on Stack Overflow asking questions like this, but none of their answers worked for me.
Can anyone please tell me how to make the harpoon the player shoots face the direction the player is facing? Thanks in advance!
Here is my code that I use-
PLAYER SCRIPT
using UnityEngine;
using System.Collections;
public class playerMove : MonoBehaviour {
// All Variables
public float speed = 10;
private Rigidbody2D rigidBody2D;
private GameObject harpoon_00001;
private bool facingRight = true;
void Awake () {
rigidBody2D = GetComponent<Rigidbody2D>();
harpoon_00001 = GameObject.Find("harpoon_00001");
}
void Update () {
if (Input.GetKeyDown(KeyCode.LeftArrow) && !facingRight) {
Flip();
}
if (Input.GetKeyDown(KeyCode.RightArrow) && facingRight) {
Flip();
}
}
void Flip () {
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
void FixedUpdate () {
float xMove = Input.GetAxis("Horizontal");
float yMove = Input.GetAxis("Vertical");
float xSpeed = xMove * speed;
float ySpeed = yMove * speed;
Vector2 newVelocity = new Vector2(xSpeed, ySpeed);
rigidBody2D.velocity = newVelocity;
if (Input.GetKeyDown("space")) {
GetComponent<AudioSource>().Play();
Instantiate(harpoon_00001,transform.position,transform.rotation);
}
}
}
HARPOON SCRIPT
using UnityEngine;
using System.Collections;
public class harpoonScript : MonoBehaviour {
// Public variable
public int speed = 6;
private Rigidbody2D r2d;
// Function called once when the bullet is created
void Start () {
// Get the rigidbody component
r2d = GetComponent<Rigidbody2D>();
// Make the bullet move upward
float ySpeed = 0;
float xSpeed = -8;
Vector2 newVelocity = new Vector2(xSpeed, ySpeed);
r2d.velocity = newVelocity;
}
void Update () {
if (Input.GetKeyDown(KeyCode.LeftArrow)) {
float xSpeed = -8;
}
if (Input.GetKeyDown(KeyCode.RightArrow)) {
float xSpeed = 8;
}
}
void OnTriggerEnter2D(Collider2D other) //hero hits side of enemy
{
Destroy(other.gameObject.GetComponent<Collider2D>()); //Remove collider to avoid audio replaying
other.gameObject.GetComponent<Renderer>().enabled = false; //Make object invisible
Destroy(other.gameObject, 0.626f); //Destroy object when audio is done playing, destroying it before will cause the audio to stop
}
}
You already defining a variable facingRight to know the direction of the the player. You can use that knowledge to control the harpoon.
For example:
// this line creates a new object, which has harpoonScript attached to it.
// In unity editor, you drag and drop this prefab(harpoon_00001) into right place.
// transform.position is used for the starting point of the fire. You can also add +-some_vector3 for better placement
// Quaternion.identity means no rotation.
harpoonScript harpoon = Instantiate(harpoon_00001,transform.position, Quaternion.identity) as harpoonScript;
// Assuming harpoon prefab already facing to right
if (!facingRight) {
// Maybe, not required
harpoon.transform.eulerAngles = new Vector3(0f, 0f, 180f); // Face backward
Vector3 theScale = harpoon.transform.localScale;
theScale.y *= -1;
harpoon.transform.localScale = theScale; // Flip on y axis
}