transform.position not working in Unity 3d - c#

I'm really new to Unity 3d and I'm trying to make a respawn with my character. It seems that the answer is really easy but I cannot see why my code is not working. If this is a duplicate, let me know.
public Vector3 PointSpawn;
void Start()
{
PointSpawn = gameObject.transform.position;
}
void Update()
{
if (gameObject.transform.position.y < 10)
{
gameObject.transform.position = PointSpawn; // This doesn't work
// gameObject.transform.LookAt(PointSpawn); ---> This DOES work ok
}
}
Parallel Script
public float HorizontalMove;
public float VerticalMove;
private Vector3 playerInput;
public CharacterController player;
public float MoveSpeed;
private Vector3 movePlayer;
public float gravity = 9.8f;
public float fallVelocity;
public float JumpForce;
public bool DoubleJump = false;
public Camera mainCamera;
private Vector3 camForward;
private Vector3 camRight;
void Start()
{
player = GetComponent<CharacterController>();
}
void Update()
{
HorizontalMove = Input.GetAxis("Horizontal");
VerticalMove = Input.GetAxis("Vertical");
playerInput = new Vector3(HorizontalMove, 0, VerticalMove);
playerInput = Vector3.ClampMagnitude(playerInput, 1);
CamDirection();
movePlayer = playerInput.x * camRight + playerInput.z * camForward;
movePlayer = movePlayer * MoveSpeed;
player.transform.LookAt(player.transform.position + movePlayer);
setGravity();
PlayerSkills();
player.Move(movePlayer * Time.deltaTime );
}
void CamDirection()
{
camForward = mainCamera.transform.forward;
camRight = mainCamera.transform.right;
camForward.y = 0;
camRight.y = 0;
camForward = camForward.normalized;
camRight = camRight.normalized;
}
void PlayerSkills()
{
if (player.isGrounded && Input.GetButtonDown("Jump"))
{
fallVelocity = JumpForce;
movePlayer.y = fallVelocity;
DoubleJump = true;
}
else if (player.isGrounded == false && Input.GetButtonDown("Jump") && DoubleJump == true)
{
fallVelocity = JumpForce *2;
movePlayer.y = fallVelocity;
DoubleJump = false;
}
}
void setGravity()
{
if (player.isGrounded)
{
fallVelocity = -gravity * Time.deltaTime;
movePlayer.y = fallVelocity;
}
else
{
fallVelocity -= gravity * Time.deltaTime;
movePlayer.y = fallVelocity;
}
}
Thanks in advance!

Just so the answer to the question is not in the comments:
The original problem is that the assignment gameObject.transform.position = PointSpawn appeared to do nothing. As the line is written properly, the position of this gameObject, must have been getting overwritten elsewhere.
With the addition of OP's movement script, the position of the player was getting overwritten in the movement's Update function. As the other assignment was being done in Update, the call order was not guaranteed to work as intended. The fix is either to assure that the movement Update is run not the frame of the new position assignment or to move the conditional and the assignment to a function that always runs after Update regardless of script execution order, LateUpdate.

Related

Unity3D go down on slopes with a animated character

I'm developping a 3D game Unity with a squirrel as the player.
I'm struggling with a problem of slopes. I know, there are a bunch of tutorial to go down a slope whithout 'floating in the air while walking' but I didn't find a fine solution. I think it's because of the horizontal animations of the squirrel (maybe). I have tried with addForce, with a modified speed, with gravity... (maybe I implemented it wrong). I know I can check if I'm in the air or not with CharacterController.isGrounded but I can't force the squirrel to stick on the slope while running or walking. I'm sorry by advance if my question is too vague or simple.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class Squirrel : MonoBehaviour {
Animator squirrel;
public float gravity = 1.0f;
private Vector3 moveDirection = Vector3.zero;
float axisH, axisV;
public static int munitions = 0;
Rigidbody rb;
[SerializeField]
float walkSpeed = 2f, runSpeed = 8f, rotSpeed = 100f, jumpForce = 350;
private bool isJumpKeyDown = false;
[SerializeField] bool isJumping = false;
Animator characterAnimator;
int JumpCount = 0;
public int MaxJumps = 1; //Maximum amount of jumps (i.e. 2 for double jumps)
[SerializeField] GameObject nb_munitions;
CharacterController characterController;
// Use this for initialization
void Start () {
munitions = 0;
squirrel = GetComponent<Animator>();
rb = GetComponentInChildren<Rigidbody>();
characterAnimator = GetComponent<Animator>();
JumpCount = MaxJumps;
characterController = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
GetInput();
nb_munitions.GetComponent<Text>().text = "Glands : " + munitions; //Affichage du score
Move();
}
private void FixedUpdate()
{
if (isJumpKeyDown)
{
squirrel.SetTrigger("jump");
JumpCount -= 1;
isJumpKeyDown = false;
}
}
public void GetInput()
{
axisV = Input.GetAxis("Vertical");
axisH = Input.GetAxis("Horizontal");
}
private void Move()
{
if (characterController.isGrounded)
{
//On the ground
}
else
{
//on the air
}
if (axisV > 0)
{
if (Input.GetKeyDown(KeyCode.LeftControl))
{
transform.position += Vector3.forward * walkSpeed * Time.deltaTime;
squirrel.SetBool("walk", true);
}
else
{
transform.position += Vector3.forward * runSpeed * Time.deltaTime;
squirrel.SetFloat("run", axisV);
squirrel.SetBool("walk", false);
}
}
else
{
squirrel.SetFloat("run", 0);
}
if (axisH != 0 && axisV == 0)
{
squirrel.SetFloat("h", axisH);
}
else
{
squirrel.SetFloat("h", 0);
}
if (axisH != 0)
{
transform.Rotate(Vector3.up * rotSpeed * Time.deltaTime * axisH);
}
if (Input.GetKeyDown(KeyCode.Space))
{
if (JumpCount > 0)
{
isJumpKeyDown = true;
}
}
//Call munitions
if (Input.GetKeyDown(KeyCode.LeftShift))
{
if (Squirrel.munitions > 0)
{
SpawnerScript.Instance.NewSpawnRequest();
munitions--;
}
}
}
}
You can try to get the angle of the slope and make it the pitch for the mesh of the squirrel.
I finally found the problem. My C# script "overwrited" the CharacterController and did not allow the squirrel to go down the slopes. Make sure you follow a move script that "respects" the CharacterController (if you pick one or you'll be fighting windmills).

Unity - how to make an object face the direction of its movement?

I'm trying to make a character prefab face the direction in which its moving. I've tired all sorts of things, with and without rigidbodies but nothing seems to work. The thing is, it does actually face in the correct direction. But once its there, it starts to rotate the whole prefab and it goes down into the ground.
The character holds a 3D shield, and goes towards a tower. So once it reaches the tower it raises the shield which in turn rotates the whole character down into the ground. I would like it to just rotate in the X and Z axis and never change the Y axis.
Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BlockRadar : MonoBehaviour
{
// Start is called before the first frame update
public Transform Tower;
private GameObject[] multipleBlocks;
public Transform closestBlock;
public bool blockContact;
public float currentDistance;
public float stopDistance;
public Animator animator;
public int damage;
public float attackspeed;
private float canAttack;
public float moveSpeed = 5f;
public Vector3 distance;
private Vector3 movement;
void Start()
{
closestBlock = null;
blockContact = false;
}
// Update is called once per frame
void Update()
{
Vector3 pos = transform.position;
pos.y = 0;
pos.x = 0;
transform.position = pos;
closestBlock = getClosestBlock();
closestBlock.gameObject.GetComponent<Renderer>().material.color = new Color(1, 0.7f, 0, 1);
Vector3 direction = closestBlock.position - transform.position;
direction.Normalize();
movement = direction;
float dist = Vector3.Distance(closestBlock.position, transform.position);
if (dist <= 1.5f)
{
{
blockContact = true;
animator.SetBool("Moving", false);
Debug.Log("Now touching block");
if (attackspeed <= canAttack)
{
Attack();
canAttack = 0f;
}
else
{
canAttack += Time.deltaTime;
}
}
}
if (dist > 1.5f)
{
transform.forward = movement;
blockContact = false;
Debug.Log("Lost contact with block");
animator.SetBool("Moving", true);
moveCharacter(movement);
}
}
public void Attack()
{
Debug.Log("ATTACKING!");
Damage(closestBlock.transform);
animator.SetTrigger("Attacking");
}
private void FixedUpdate()
{
}
void moveCharacter(Vector3 direction)
{
transform.Translate(direction * moveSpeed * Time.deltaTime, Space.World);
}
void DistanceToTower()
{
if (Tower)
{
float dist = Vector3.Distance(Tower.position, transform.position);
if (dist <= 1)
{
{
blockContact = true;
Debug.Log("Now touching block");
if (attackspeed <= canAttack)
{
Attack();
canAttack = 0f;
}
else
{
canAttack += Time.deltaTime;
}
}
}
}
}
//when the object carrying this script is destroyed
private void OnDestroy()
{
if (closestBlock !=null)
{
closestBlock.gameObject.GetComponent<Renderer>().material.color = new Color(0, 0, 0, 0);
}
}
public Transform getClosestBlock()
{
multipleBlocks = GameObject.FindGameObjectsWithTag("Block");
float closestDistance = Mathf.Infinity;
Transform trans = null;
//finds all blocks in the scene
foreach (GameObject go in multipleBlocks)
{
currentDistance = Vector3.Distance(transform.position, go.transform.position);
if (currentDistance < closestDistance)
{
closestDistance = currentDistance;
trans = go.transform;
}
}
return trans;
}
void Damage(Transform block)
{
Tower_Stats e = block.GetComponent<Tower_Stats>();
if (e != null)
{
e.TakeDamage(damage);
}
}
}
I would be really, really grateful for any help. As I said before I used to have rigidbodies on the character, but I removed them since I thought maybe they were the fault. But doesnt seem like it. One other thing I've noticed is that when the prefab is instantiated, its children doesnt have the correct position values. Not sure why. But if that could be a clue I just thought I'd let you know.

How to get a character to turn in the direction of the camera? [Unity3D]

I've hit a roadblock where when I move the camera, while moving, the character rotates on the spot however, their direction in where they are heading changes when I update the left thumbstick.
This is odd as updating it in Update doesn't work and forces the character to move in circles and placing it in a bit of script that updates with the right thumbstick is moved, causes the character to rotate and move in very different directions that what I want it to go in. This is temporarily fixed when I move the left thumbstick, updating the character's movement.
The controls for this are: Left Thumbstick - Move player, Right Thumbstick - Move camera, East Button - Jump, North Button - Run.
The goal is to allow the character to rotate themselves as well as their direction when I move the camera rather than them only updating their direction when I move the left thumbstick.
Before the code, these are the packages I'm currently using within Unity that effect this: Cinemachine & Input System.
Here's the movement code that this is effecting:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
using UnityEngine.AI;
using UnityEngine.InputSystem;
public class PlayerMovement : MonoBehaviour
{
private DefaultControls controls;
[Header("Unity General")]
[SerializeField]
private CharacterController controller;
public Transform cameraTransform;
public InputActionReference cameraControl;
[Header("General Settings")]//Player movement.
public bool canMovePlayer;
private Vector2 currentMovementInput;
private Vector3 currentMovement;
private Vector3 currentRunMovement;
private bool isMovementPressed;
private bool isRunPressed;
[Space]//Animator stuff.
public Animator characterAnimator;
private int isWalkingHash;
private int isRunningHash;
[Space]//Player running speed & how fast the player will turn when going left or right.
public float rotationFactorPerFrame = 15.0f;
public float runMultiplier = 3.0f;
[Space]//Default gravity for when the player is falling and gravity for when the player is grounded.
public float gravity = -9.81f;
public float groundedGravity = -0.05f;
[Space]//Playing jumping.
public float initialJumpVelocity;
private bool isJumpPressed = false;
private float maxJumpHeight = 1f;
private float maxJumpTime = 0.5f;
private bool isJumping = false;
private int isJumpingHash;
private bool isJumpAnimating = false;
private void Start()
{
Cursor.lockState = CursorLockMode.Locked;
npcInteraction = GetComponent<NPCInteraction>();
}
private void Awake()
{
controls = new DefaultControls();
controller = GetComponent<CharacterController>();
isWalkingHash = Animator.StringToHash("isWalking");
isRunningHash = Animator.StringToHash("isRunning");
isJumpingHash = Animator.StringToHash("isJumping");
controls.Movement.Walking.started += OnMovementInput;
controls.Movement.Walking.canceled += OnMovementInput;
controls.Movement.Walking.performed += OnMovementInput;
controls.Movement.Run.started += OnRun;
controls.Movement.Run.canceled += OnRun;
controls.Movement.Jump.started += OnJump;
controls.Movement.Jump.canceled += OnJump;
SetupJumpVariables();
}
private void SetupJumpVariables()
{
float timeToApex = maxJumpTime / 2;
gravity = (-2 * maxJumpHeight) / Mathf.Pow(timeToApex, 2);
initialJumpVelocity = (2 * maxJumpHeight) / timeToApex;
}
private void HandleJump()
{
if (!isJumping && controller.isGrounded && isJumpPressed)
{
characterAnimator.SetBool(isJumpingHash, true);
isJumpAnimating = true;
isJumping = true;
currentMovement.y = initialJumpVelocity * 0.5f;
currentRunMovement.y = (initialJumpVelocity + 0.5f) * 0.5f;
}
else if (!isJumpPressed && isJumping && controller.isGrounded)
{
isJumping = false;
}
}
private void OnJump(InputAction.CallbackContext context)
{
isJumpPressed = context.ReadValueAsButton();
}
private void OnRun(InputAction.CallbackContext context)
{
isRunPressed = context.ReadValueAsButton();
}
private void HandleRotation()
{
Vector3 positionToLookAt;
//Change in position our character should point to.
positionToLookAt.x = currentMovement.x;
positionToLookAt.y = 0.0f;
positionToLookAt.z = currentMovement.z;
//Current rotation of our character.
Quaternion currentRotation = transform.rotation;
if (currentMovementInput != Vector2.zero)
{
//Creates a new rotation based on where the player is currently pressing.
float targetAngle = Mathf.Atan2(currentMovementInput.x, currentMovementInput.y) * Mathf.Rad2Deg + cameraTransform.eulerAngles.y;
Quaternion targetRotation = Quaternion.Euler(0f, targetAngle, 0f);
transform.rotation = Quaternion.Lerp(currentRotation, targetRotation, rotationFactorPerFrame * Time.deltaTime);
}
}
private void OnMovementInput(InputAction.CallbackContext context)
{
currentMovementInput = context.ReadValue<Vector2>();
currentMovement = new Vector3(currentMovementInput.x, 0f, currentMovementInput.y);
currentRunMovement.x = currentMovementInput.x * runMultiplier;
currentRunMovement.z = currentMovementInput.y * runMultiplier;
MovementDirection();
isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
}
private void MovementDirection()
{
currentMovement = cameraTransform.forward * currentMovement.z + cameraTransform.right * currentMovement.x;
currentMovement.y = 0f;
currentRunMovement = cameraTransform.forward * currentRunMovement.z + cameraTransform.right * currentRunMovement.x;
currentRunMovement.y = 0f;
}
private void HandleAnimation()
{
bool isWalking = characterAnimator.GetBool(isWalkingHash);
bool isRunning = characterAnimator.GetBool(isRunningHash);
if (isMovementPressed && !isWalking)
{
characterAnimator.SetBool(isWalkingHash, true);
}
else if (!isMovementPressed && isWalking)
{
characterAnimator.SetBool(isWalkingHash, false);
}
if ((isMovementPressed && isRunPressed) && !isRunning)
{
characterAnimator.SetBool(isRunningHash, true);
}
else if ((!isMovementPressed || !isRunPressed) && isRunning)
{
characterAnimator.SetBool(isRunningHash, false);
}
}
private void HandleGravity()
{
bool isFalling = currentMovement.y <= 0.0f;
float fallMultiplier = 1.5f;
if (controller.isGrounded)
{
characterAnimator.SetBool(isJumpingHash, false);
isJumpAnimating = false;
currentMovement.y = groundedGravity;
currentRunMovement.y = groundedGravity;
}
else if (isFalling)
{
float previousYVelocity = currentMovement.y;
float newYVelocity = currentMovement.y + (gravity * fallMultiplier * Time.deltaTime);
float nextYVelocity = (previousYVelocity + newYVelocity) * 0.5f;
currentMovement.y = nextYVelocity;
currentRunMovement.y = nextYVelocity;
}
else
{
float previousYVelocity = currentMovement.y;
float newYVelocity = currentMovement.y + (gravity * Time.deltaTime);
float nextYVelocity = (previousYVelocity + newYVelocity) * 0.5f;
currentMovement.y = nextYVelocity;
currentRunMovement.y = nextYVelocity;
}
}
// Update is called once per frame
public void Update()
{
HandleRotation();
HandleAnimation();
controller.Move(currentMovement * Time.deltaTime);
characterAnimator.SetFloat("Speed", controls.Movement.Walking.ReadValue<Vector2>().magnitude);
if (isRunPressed)
{
controller.Move(currentRunMovement * Time.deltaTime);
}
else
{
controller.Move(currentMovement * Time.deltaTime);
}
HandleGravity();
HandleJump();
if (cameraControl.action.triggered)
{
MovementDirection();
}
LockOnTarget();
Interaction();
}
private void OnEnable()
{
controls.Movement.Enable();
}
private void OnDisable()
{
controls.Movement.Disable();
}
}```
Before diving into your code that has quite deep stuff regarding the camara movement, find this simple way in which a gameObject can face the direction of the camera in a simple way. Just in case it helps. This answers directly your question "How to get a character to turn in the direction of the camera?"
using UnityEngine;
public class LookToCamForward : MonoBehaviour
{
void Start()
{
transform.rotation = Quaternion.LookRotation(Camera.main.transform.forward, Camera.main.transform.up);
}
}

Unity Raycasting problem in some part of the scene

I started doing some simple stuff in Unity (goal is to make a great game) so I made a simple Player Controller.
public class PlayerController : MonoBehaviour
{
public float walkingSpeed;
public float jumpSpeed;
public bool jumpFlag = false;
public float maxJumpDistance = 1.0f;
Rigidbody rb;
Collider col;
Vector3 playerSize;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
col = GetComponent<Collider>();
playerSize = col.bounds.size;
}
// Update is called once per frame
void FixedUpdate()
{
WalkHandler();
JumpHandler();
}
void WalkHandler()
{
float horizonstalAxis = Input.GetAxis("Horizontal");
float verticalAxis = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(-horizonstalAxis * walkingSpeed * Time.deltaTime, 0, -verticalAxis * walkingSpeed * Time.deltaTime);
rb.MovePosition(transform.position += movement);
}
void JumpHandler()
{
float jumpAxis = Input.GetAxis("Jump");
//Debug.Log(jumpAxis);
if (jumpAxis > 0)
{
bool isGrounded = CheckGrounded();
if (jumpFlag != true && isGrounded)
{
jumpFlag = true;
Vector3 jumpVector = new Vector3(0, jumpSpeed * Time.deltaTime, 0);
rb.AddForce(jumpVector, ForceMode.VelocityChange);
}
}
else
{
jumpFlag = false;
}
}
bool CheckGrounded()
{
Vector3 checkerPoint = transform.position + new Vector3(0, -playerSize.y / 2, 0);
bool grounded = Physics.Raycast(checkerPoint, -Vector3.up, maxJumpDistance);
return grounded;
}
I came across a wierd problem. In some parts of the scene my method JumpHandler is not working. After reaching some z coordinates, the CheckGrounded returns False instead of True, even though the Raycast direction is set down.
Can anyone help?

Player Movement using joystick based on camera facing

I am developing an offline FPS multiplayer game.
When the Player Rotation value is (0,0,0), then Player moves perfectly in direction. However, my problem is when I rotate the camera using touch input. The player can also rotate his face and press the joystick button for moving the player, but then the player should not move the direction the camera is facing.
My Joystick Script For Player
public class VirtualJoystick : MonoBehaviour, IDragHandler, IPointerUpHandler,IPointerDownHandler {
private Image bgImg;
private Image JoyStickImage;
private Vector3 InputVector;
private void Start(){
bgImg = GetComponent<Image> ();
JoyStickImage = transform.GetChild (0).GetComponent<Image> ();
}
public virtual void OnDrag(PointerEventData ped){
Vector2 pos;
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);
InputVector = new Vector3 (pos.x * 2 + 1, 0, pos.y * 2 - 1);
InputVector = (InputVector.magnitude > 1) ? InputVector.normalized : InputVector;
JoyStickImage.rectTransform.anchoredPosition = new Vector3 (InputVector.x * (bgImg.rectTransform.sizeDelta.x / 2.5f),
InputVector.z * (bgImg.rectTransform.sizeDelta.y / 2.5f));
}
}
public virtual void OnPointerDown(PointerEventData ped){
OnDrag (ped);
}
public virtual void OnPointerUp(PointerEventData ped){
InputVector = Vector3.zero;
JoyStickImage.rectTransform.anchoredPosition = Vector3.zero;
}
public float Horizontal(){
if (InputVector.x != 0) {
return InputVector.x;
} else {
return Input.GetAxis ("Horizontal");
}
}
public float Vertical(){
if (InputVector.z != 0)
return InputVector.z;
else
return Input.GetAxis ("Vertical");
}
}
My Camera Rotation Script Using Input Touch
public class SwipeCam : MonoBehaviour {
private Vector3 firstPoint;
private Vector3 secondPoint;
private float xAngle = 0.0f;
private float yAngle = 0.0f;
private float xAngleTemp = 0.0f;
private float yAngleTemp = 0.0f;
void Start(){
xAngle = 0.0f;
yAngle = 0.0f;
this.transform.rotation = Quaternion.Euler (yAngle, xAngle, 0.0f);
}
void Update() {
if (Input.touchCount > 0) {
for (int i = 0; i < Input.touchCount; i++) {
Touch touch = Input.GetTouch (i);
if (touch.position.x > Screen.width / 2) {
if (touch.phase == TouchPhase.Began) {
firstPoint = Input.GetTouch (0).position;
xAngleTemp = xAngle;
yAngleTemp = yAngle;
}
if (touch.phase == TouchPhase.Moved) {
secondPoint = Input.GetTouch (0).position;
xAngle = xAngleTemp + (secondPoint.x - firstPoint.x) * 180.0f / Screen.width;
yAngle = yAngleTemp + (secondPoint.y - firstPoint.y) * 180.0f / -Screen.height;
yAngle = Mathf.Clamp (yAngle, -30f, 30f);
this.transform.rotation = Quaternion.Euler (yAngle, xAngle, 0.0f);
this.gameObject.GetComponentInParent<FPScontroller> ().transform.rotation = Quaternion.Euler (0.0f, xAngle, 0.0f);
//this.gameObject.GetComponentInParent<FPScontroller> ().transform.rotation = Quaternion.LookRotation(Vector3.forward,Vector3.up);
}
}
}
}
}
}
Where should I change my code to fix the facing the camera direction to player issue.
That is my Player Script (FPSController.cs)
public class FPScontroller : MonoBehaviour {
// Should this script respond to input?
public bool canControl = true;
public GameObject lookObj; //This is root object that containc MainCamera, Weapons etc.
public GameObject joystick;
bool useFixedUpdate = false;
//Check when run, walk or when can run or not
[HideInInspector]
public bool Running ;
[HideInInspector]
public bool Walking;
[HideInInspector]
public bool canRun;
[HideInInspector]
public Vector3 rorationDir;
//Ladder variables
private GameObject mainCamera = null;
[HideInInspector]
public bool onLadder = false;
//private float ladderHopSpeed = 6.0f;
// For the next variables, #System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view.
// Very handy for organization!
// The current global direction we want the character to move in.
[System.NonSerialized]
public Vector3 inputMoveDirection = Vector3.zero;
// Is the jump button held down? We use this interface instead of checking
// for the jump button directly so this script can also be used by AIs.
[System.NonSerialized]
public bool inputJump = false;
[HideInInspector]
public bool inputRun = false;
[HideInInspector]
public bool inputCrouch = false;
[HideInInspector]
public bool inputProne = false;
[System.Serializable]
public class FPScontrollerMovement {
// The maximum horizontal speed when moving
[HideInInspector]
public float maxForwardSpeed = 10.0f;
[HideInInspector]
public float maxSidewaysSpeed = 10.0f;
[HideInInspector]
public float maxBackwardsSpeed = 10.0f;
//Run and walk variables
public float WalkSpeed = 6.0f;
public float RunSpeed = 9.0f;
//Crouch
public bool canCrouch = true;
public float CrouchSpeed = 3.0f;
public float crouchHeight = 1.5f;
public float crouchSmooth = 8;
//prone
public bool canProne = true;
public float ProneSpeed = 1.5f;
public float proneHeight = 0.7f;
// Curve for multiplying speed based on slope (negative = downwards)
public AnimationCurve slopeSpeedMultiplier = new AnimationCurve(new Keyframe(-90, 1), new Keyframe(0, 1), new Keyframe(90, 0));
// How fast does the character change speeds? Higher is faster.
public float maxGroundAcceleration = 30.0f;
public float maxAirAcceleration = 20.0f;
// The gravity for the character
public float gravity = 10.0f;
public float maxFallSpeed = 20.0f;
[HideInInspector]
public bool enableGravity = true;
// For the next variables, #System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view.
// Very handy for organization!
// The last collision flags returned from controller.Move
[System.NonSerialized]
public CollisionFlags collisionFlags;
// We will keep track of the character's current velocity,
[System.NonSerialized]
public Vector3 velocity;
// This keeps track of our current velocity while we're not grounded
[System.NonSerialized]
public Vector3 frameVelocity = Vector3.zero;
[System.NonSerialized]
public Vector3 hitPoint = Vector3.zero;
[System.NonSerialized]
public Vector3 lastHitPoint = new Vector3(Mathf.Infinity, 0, 0);
}
public FPScontrollerMovement movement = new FPScontrollerMovement();
void Awake () {
if (GetComponent<NetworkView> ().isMine) {
joystick = GameObject.Find ("Joystick");
controller = gameObject.GetComponent<CharacterController>();
standartHeight = controller.height;
/*if(GameObject.FindWithTag("LookObject") != null){
lookObj = GameObject.FindWithTag("LookObject");
}*/
centerY = controller.center.y;
tr = transform;
canRun = true;
canStand = true;
StartCoroutine(setupBools());
}
}
void Update () {
if (GetComponent<NetworkView> ().isMine) {
if (!useFixedUpdate) {
UpdateFunction ();
}
movement.velocity.x = joystick.GetComponent<VirtualJoystick> ().Horizontal () * 5f;
movement.velocity.z = joystick.GetComponent<VirtualJoystick> ().Vertical () * 5f;
//Run input
if (Input.GetAxis ("Vertical") > 0.1f && inputRun && canRun && !onLadder && Walking) {
if (canStand && canStandCrouch) {
OnRunning ();
}
} else {
OffRunning ();
}
//Check when walk or not
if ((movement.velocity.x > 0.01f || movement.velocity.z > 0.01f) || (movement.velocity.x < -0.01f || movement.velocity.z < -0.01f)) {
RunAnimation1 ();
Debug.Log ("Forward");
Walking = true;
}else if (movement.velocity.x > 0.01f) {
Walking = true;
Debug.Log ("Right");
} else if (movement.velocity.x < -0.01f) {
Walking = true;
Debug.Log ("Left");
} else {
RunAnimation ();
Walking = false;
}
if (!canControl)
return;
if (movement.canCrouch) {
if (!onLadder) {
Crouch ();
}
}
if (movement.canProne) {
if (!onLadder) {
Prone ();
}
}
if (onLadder) {
grounded = false;
crouch = false;
prone = false;
}
if (!crouch && !prone && controller.height < standartHeight - 0.01f) {
controller.height = Mathf.Lerp (controller.height, standartHeight, Time.deltaTime / movement.crouchSmooth);
controller.center = new Vector3 (controller.center.x, Mathf.Lerp (controller.center.y, centerY, Time.deltaTime / movement.crouchSmooth), controller.center.z);
lookObj.transform.localPosition = new Vector3 (lookObj.transform.localPosition.x, Mathf.Lerp (lookObj.transform.localPosition.y, standartHeight, Time.deltaTime / movement.crouchSmooth), lookObj.transform.localPosition.z);
}
}
}
void RunAnimation(){
GetComponent<NetworkView> ().RPC ("SysnAnimation", RPCMode.All, 0);
}
void RunAnimation1(){
GetComponent<NetworkView> ().RPC ("SysnAnimation", RPCMode.All, 1);
}
void RunAnimation2(){
GetComponent<NetworkView> ().RPC ("SysnAnimation", RPCMode.All, 2);
}
[RPC]
void SysnAnimation(int index){
if (index == 0) {
GetComponent<Animator> ().Play ("Idle Aim");
} else if (index == 1) {
GetComponent<Animator> ().Play ("Walk Aiming");
} else if (index == 2) {
GetComponent<Animator> ().Play ("Jump");
}
}
void OnRunning (){
Debug.Log ("Run");
Running = true;
movement.maxForwardSpeed = movement.RunSpeed;
movement.maxSidewaysSpeed = movement.RunSpeed;
//Make bigger extra height when player run to increase jump distance
jumping.extraHeight = jumping.baseHeight + 0.15f;
}
void OffRunning (){
Running = false;
if(crouch || prone)
return;
movement.maxForwardSpeed = movement.WalkSpeed;
movement.maxSidewaysSpeed = movement.WalkSpeed;
movement.maxBackwardsSpeed = movement.WalkSpeed/2;
//Change extraheight value to default when player walk
jumping.extraHeight = jumping.baseHeight;
}}
Your camera and joystick code looks fine, but that's not where the problem is.
I'll assume your player movement code looks something like this:
Get input X and Y
Move player right by X, forward by Y
In code form, that might look something like this:
//returns the world-space direction that player wants to move
Vector3 GetDesiredMovement(float inputForward, float inputRight) {
//get a vector pointing to player's right
Vector3 dirRight = Camera.main.transform.right;
dirRight.y = 0f;
dirRight.Normalize();
//get a vector pointing to player's front
Vector3 dirForward = Camera.main.transform.forward;
dirForward.y = 0f;
dirForward.Normalize();
//calculate desired movement based on input
Vector3 desiredMovement = (dirForward * inputForward) + (dirRight * inputRight);
desiredMovement.Normalize();
return desiredMovement;
}
What if "right" and "forward" need to be relative to some other object in the scene, such as a camera? It's easier than you might think: just read those values directly from the camera's transform component.
You could do that by replacing just two lines from the above example:
Vector3 dirRight = Camera.main.transform.right;
Vector3 dirForward = Camera.main.transform.forward;
I solved the problem of basing player movement of the camera's direction.
In my Player's script there are two lines that read joystick input:
movement.velocity.x = joystick.GetComponent<VirtualJoystick> ().Horizontal () * 5f;
movement.velocity.z = joystick.GetComponent<VirtualJoystick> ().Vertical () * 5f;`
I changed them to this:
Vector3 DirectionVector =
new Vector3 (joystick.GetComponent<VirtualJoystick> ().Horizontal (), 0f, joystick.GetComponent<VirtualJoystick> ().Vertical ());
movement.velocity = transform.rotation * DirectionVector * 10f;
Directly add joystick value in movement vector. I just multiply it to the joystick input vector and solve my problem.
Now the player moves based on the player rotation and where the camera is facing.
Thanks everyone for help.

Categories