I have two problems with implementing two Virtual Joysticks in Unity 5: one for player movement (grey color) and the second for camera (orange color) please see the following screenshot:
My problems:
For the Virtual Joystick responsible for player movement, the player object does not rotate in the same direction the Joystick is pressed , it's moving in all directions but not facing the same direction that the Joystick is pressed.
The camera can see through the terrain/ground. How do I prevent that?
The script I'm using from Virtual Joystick :
using UnityEngine; using System.Collections; using UnityEngine.UI; using UnityEngine.EventSystems;
public class VirtualJoystick : MonoBehaviour,IDragHandler,IPointerUpHandler,IPointerDownHandler {
private Image bgImg;
private Image joystickImg;
public Vector3 InputDirection{ set; get;}
// Use this for initialization
void Start () {
bgImg = GetComponent<Image> ();
joystickImg = transform.GetChild (0).GetComponent<Image> ();
InputDirection = Vector3.zero;
}
// Update is called once per frame
//void Update () {
//}
public virtual void OnDrag(PointerEventData ped)
{
Vector2 pos = Vector2.zero;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle
(bgImg.rectTransform,
ped.position,
ped.pressEventCamera,
out pos)) {
pos.x=(pos.x/bgImg.rectTransform.sizeDelta.x);
pos.y=(pos.y/bgImg.rectTransform.sizeDelta.y);
float x=(bgImg.rectTransform.pivot.x==1) ? pos.x*2+1 : pos.x*2-1;
float y=(bgImg.rectTransform.pivot.y==1) ? pos.y*2+1 : pos.y*2-1;
InputDirection=new Vector3(x,0,y);
InputDirection=(InputDirection.magnitude>1) ? InputDirection.normalized : InputDirection;
joystickImg.rectTransform.anchoredPosition=
new Vector3(InputDirection.x*(bgImg.rectTransform.sizeDelta.x/3),InputDirection.z*(bgImg.rectTransform.sizeDelta.y/3));
Debug.Log(InputDirection);
}
}
public virtual void OnPointerDown(PointerEventData ped)
{
OnDrag (ped);
}
public virtual void OnPointerUp(PointerEventData ped)
{
//Here is the problem it just goes to zero so fast so my character also moves so fast...how can i make it so motth
InputDirection =Vector3.zero;
joystickImg.rectTransform.anchoredPosition =Vector3.zero;
}
}
The script to move the player:
using UnityEngine; using System.Collections;
public class Motor : MonoBehaviour {
public float moveSpeed = 5.0f;
public float drag = 0.5f;
public float terminalRotationSpeed = 25.0f;
private Rigidbody controller;
private Transform camtransform;
public VirtualJoystick movejoystick;
private void Start()
{
controller =GetComponent<Rigidbody>();
controller.maxAngularVelocity = terminalRotationSpeed;
controller.drag = drag;
camtransform = Camera.main.transform;
}
private void Update ()
{
Vector3 dir = Vector3.zero;
dir.x = Input.GetAxis ("Horizontal");
dir.z = Input.GetAxis ("Vertical");
if (dir.magnitude > 1)
dir.Normalize ();
if (movejoystick.InputDirection != Vector3.zero) {
dir = movejoystick.InputDirection;
}
Vector3 rotatedDir = camtransform.TransformDirection (dir);
rotatedDir = new Vector3 (rotatedDir.x, 0, rotatedDir.z);
rotatedDir = rotatedDir.normalized * dir.magnitude;
controller.AddForce (dir * moveSpeed);
Quaternion eulerRot = Quaternion.Euler(0.0f, 0.0f, rotatedDir.x);
transform.rotation = Quaternion.Slerp(transform.rotation, eulerRot, Time.deltaTime * 10);
}
}
The script I'm using for the camera:
using UnityEngine;
using System.Collections;
public class FreeCamera :
MonoBehaviour {
public Transform lookAt;
public VirtualJoystick camerajs;
private float distance = 200.0f;
private float currentx = 0.0f;
private float currenty = 0.0f;
private float sensitivityx = 1.0f;
private float sensitivityy = 1.0f;
private void Update()
{
currentx += camerajs.InputDirection.x * sensitivityx;
currenty += camerajs.InputDirection.z * sensitivityy;
}
private void LateUpdate()
{
Vector3 dir = new Vector3(0, 0, -distance);
Quaternion rotation = Quaternion.Euler(currenty, currentx, 0);
transform.position = lookAt.position + rotation * dir;
transform.LookAt(lookAt);
}
}
more screenshots :
For question 1:
The code below first turns according to joystick-x direction and then move forward/backward according to joystick-y. In Motor.Update:
private void Update ()
{
Vector3 dir = Vector3.zero;
dir.x = Input.GetAxis ("Horizontal");
dir.z = Input.GetAxis ("Vertical");
if (dir.magnitude > 1)
dir.Normalize ();
if (movejoystick.InputDirection != Vector3.zero) {
dir = movejoystick.InputDirection;
}
Vector3 rotatedDir = transform.TransformDirection (dir); // world direction of joystick direction
Vector3 newDir = Vector3.RotateTowards(transform.forward, rotatedDir, Time.deltaTime * 10f, 0.0F); // turn towards joystick direction
transform.rotation = Quaternion.LookRotation(newDir); // set the new direction
controller.AddForce (transform.forward * moveSpeed * dir.z); // scale force by joystick up/down
}
Related
I am trying to make a first-person game in Unity but I keep having issues with my character controller. The player keeps rotating when it collides with objects that have physics (Or rigidbody)
It doesn't rotate when it collides with objects that don't have physics.
It's not my mouse because my MouseX and Y Values aren't changing.
Here is the code for the Player
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
public class PlayerControllerRB : MonoBehaviour
{
public float speed = 10f;
public float jumpHeight = 4.65f;
[SerializeField] private Rigidbody rb;
private PlayerInput playerInput;
private PlayerInput.OnFootActions onFoot;
[SerializeField] private Camera cam;
public float xSensitivity = 8f;
public float ySensitivity = 8f;
private float xRotation;
private float yMovement;
private float hMovement;
[SerializeField] private Transform Feet;
[SerializeField] public LayerMask Ground;
private void Awake()
{
rb = GetComponent<Rigidbody>();
playerInput = new PlayerInput();
onFoot = playerInput.onFoot;
onFoot.Jump.performed += ctx => Jump();
}
private void Start()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
#region
private void OnEnable()
{
playerInput.Enable();
onFoot.Enable();
}
private void OnDisable()
{
playerInput.Disable();
onFoot.Disable();
}
#endregion
private void FixedUpdate()
{
ProcessMove(onFoot.Movement.ReadValue<Vector2>());
}
private void Update()
{
ProcessLook(onFoot.Look.ReadValue<Vector2>());
}
void ProcessMove(Vector2 input)
{
Vector3 MoveDirection = Vector3.zero;
hMovement = input.x;
yMovement = input.y;
MoveDirection = transform.forward * yMovement + transform.right * hMovement;
//MoveDirection.y = rb.velocity.y;
Debug.Log(MoveDirection * speed);
rb.AddForce(MoveDirection * speed, ForceMode.Acceleration);
}
void Jump()
{
Ray ray = new Ray(Feet.position, Vector3.down);
RaycastHit info;
if(Physics.Raycast(ray, out info, 0.3f, Ground))
{
rb.AddForce(Vector3.up * jumpHeight, ForceMode.Impulse);
}
}
void ProcessLook(Vector2 input)
{
float MouseY = input.y;
float MouseX = input.x;
xRotation -= (MouseY * Time.deltaTime) * ySensitivity;
xRotation = Mathf.Clamp(xRotation, -80f, 80f);
cam.transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
transform.Rotate(Vector3.up * (MouseX * Time.deltaTime) * xSensitivity);
}
}
I tried freezing the y rotation but then I get a jittry camera.
Can anyone help me? It would also be nice if you had any recommendations to improve the controller.
Please comment if you need any more information. Sorry if the post is junk, I'm new to Stackoverflow
Well, you said It doesn't rotate when it collides with objects that don't have physics. In order to use the colliders one of them has to have a rigibody component. So if that's the case maybe is the script that is inside the oncollisionenter causing the problems. But I don't see any oncollisionenter script here
Please tell me, when I move the character with the joystick, the character will get stuck in a regular wall. What could be the problem?
Below is a video demonstration.
When moving with the buttons, the character does not get stuck.
https://www.youtube.com/watch?v=9SiQzLAq-kU
Thanks in advance)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovePersonal : MonoBehaviour
{
public float speedMove;
public float jumpPower;
private float gravityForce;
private Vector3 moveVector;
private CharacterController ch_controller;
private Animator ch_animator;
private MobileController mContr;
// Start is called before the first frame update
private void Start()
{
ch_controller = GetComponent<CharacterController>();
ch_animator = GetComponent<Animator>();
mContr = GameObject.FindGameObjectWithTag("joy").GetComponent<MobileController>();
}
// Update is called once per frame
private void Update()
{
CharacterMove();
GamingGravity();
}
private void CharacterMove() {
if (ch_controller.isGrounded) {
moveVector = Vector3.zero;
moveVector.x = mContr.Horizontal() * speedMove;
moveVector.z = mContr.Vertical() * speedMove;
if(Vector3.Angle(Vector3.forward, moveVector)>1f || Vector3.Angle(Vector3.forward, moveVector) == 0) {
Vector3 direct = Vector3.RotateTowards(transform.forward, moveVector, speedMove, 0.0f);
transform.rotation = Quaternion.LookRotation(direct);
}
}
else {
}
moveVector.y = gravityForce;
ch_controller.Move(moveVector * Time.deltaTime);
}
private void GamingGravity() {
if (!ch_controller.isGrounded) gravityForce -=20f * Time.deltaTime;
else gravityForce = -1f;
if(Input.GetKeyDown(KeyCode.Space) && ch_controller.isGrounded) gravityForce = jumpPower;
}
}
i have been recreating my jump code, i have it all done but i can't add force or anything else.
Here's my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class pBeh : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1;
public float Gravity = 9.8f;
private float velocity = 0;
private Camera mainCam;
public Rigidbody rb;
public float jumpSpeed = 5.2f;
private Vector3 movingDirection = Vector3.zero;
public CharacterController controller;
public float speed;
float turnSmoothVelocity;
public float turnSmoothTime;
public bool canJump = false;
private void Start()
{
characterController = GetComponent<CharacterController>();
mainCam = Camera.main;
}
void Update()
{
// player movement - forward, backward, left, right
float horizontal = Input.GetAxis("Horizontal") * 10;
float vertical = Input.GetAxis("Vertical") * 10;
Vector3 camRightFlat = new Vector3(mainCam.transform.right.x, 0,
mainCam.transform.right.z).normalized;
Vector3 camForwardFlat = new Vector3(mainCam.transform.forward.x, 0,
mainCam.transform.forward.z).normalized;
characterController.Move((camRightFlat * horizontal + camForwardFlat * vertical)
* Time.deltaTime);
// Gravity
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
if (canJump == true && Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Jumped");/*
transform.Translate(Vector3.up * 5.0f * Time.deltaTime);
rb.AddRelativeForce(Vector3.up * 8.0f);
rb.AddForce(Vector3.up * 8.0f)
i have tried a lot more, but it just doesn't work.
The sphere (Player) does nothing or shakes.
*/
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "enemy")
{
SceneManager.LoadScene("SampleScene");
}
}
void FixedUpdate()
{
if ((controller.collisionFlags & CollisionFlags.Below) != 0)
{
//Debug.Log("ground");
canJump = true;
}
else
{
canJump = false;
}
}
As i said it works just fine i just can't find reason why i cannot jump.
I have all character controller right and rigidbody too. If you could help i would be happy.
Btw i am beginner so i copied movement to be same as camera. Thanks!
From what I know, rigidbody and character controller do not work together (on the same object) so you have to choose one or the other, if you are using rigidbody then a ground check or similiar stuff would not be necessary since rigidbody is using unity physicis system so a lot of the stuff would be already done for you to simulate physics but you should still read thru the document
i am using unity to ,make a game through c# and i want to ask if how to make the player scale y_axis down when pressing a key on PC and scaling y_axis up when the key is released.
using System;
using UnityEngine;
public class Playermovement : MonoBehaviour {
public Rigidbody rb;
public float forwardforce = 2000f;
public float sideswaysforce = 500f;
Vector3 small;
// Update is called once per frame
void FixedUpdate()
{
rb.AddForce(0, 0, forwardforce * Time.deltaTime);
if(Input.GetKey("d"))
{
rb.AddForce(sideswaysforce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
}
if (Input.GetKey("a"))
{
rb.AddForce(-sideswaysforce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
}
if(Input.GetKey("f"))
{
small = transform.localScale;
small.y = 0.5f;
transform.localScale = small;
}
}
}
}
You can do something like this, in your current code you could continuously shrink the scale and nothing resets it.
public Vector3 halfScale;
public Vector3 originalScale;
void Start() {
originalScale = transform.localScale;
halfScale = originalScale;
halfScale.y = halfScale.y * 0.5f;
}
//...in your fixedupdate loop
if(Input.GetKey("f"))
{
transform.localScale = halfScale;
} else {
transform.localScale = originalScale;
}
How would I be able to set the speed for going forward and back in the Void FixedUpdate? Or is there a better way for doing this? I need to use the character controller though.
using UnityEngine;
using System.Collections;
public class CharacterControllerz : MonoBehaviour {
public float speed;
private CharacterController playerController;
void Start()
{
playerController = GetComponent<CharacterController>();
}
void Update()
{
}
void FixedUpdate()
{
if (Input.GetKey("right"))
{
playerController.Move (Vector3.forward);
Debug.Log ("RIGHT");
}
if (Input.GetKey("left"))
{
playerController.Move (Vector3.back);
Debug.Log ("LEFT");
}
playerController.Move (Vector3.left);
}
}
public float speed = 5f;
public float jumpStrenght = 8f;
public float gravity = 20f;
private Vector3 moveDirections = new Vector3();
private Vector3 inputs = new Vector3();
void FixedUpdate()
{
CharacterController cc = GetComponent<CharacterController>();
if (cc.isGrounded)
{
if (Input.GetKey("right"))
inputs.z = 1;
if (Input.GetKey("left"))
inputs.z = -1;
if (Input.GetKey("up"))
inputs.y = jumpStrenght;
moveDirections = transform.TransformDirection(inputs.x, 0, inputs.z) * speed;
}
moveDirections.y = inputs.y - gravity;
cc.Move(moveDirections * Time.deltaTime);
}
I think that's what you want but you may have to switch the axis.
Edit: Why is TransformDirection used? Because we want to move the object in a direction which shouldn't be relativ to the object's rotation.