Child object rotation relative to parent - c#

I've been trying to rotate my player's gun target along with the player. My player keeps shooting to right side even though he's facing left.
I've created a target called Firepoint, it's set to as a child Object of the player. I want it to change as the character changes it's direction.
Any help is appreciated.
Here's the code of the player.
public void Move()
{
float controlThrow = CrossPlatformInputManager.GetAxis("Horizontal");
Vector2 playerVelocity = new Vector2(controlThrow * runSpeed, myRigidBody.velocity.y);
myRigidBody.velocity = playerVelocity;
bool playerHasHorizontalSpeed = Mathf.Abs(myRigidBody.velocity.x) > Mathf.Epsilon;
myAnimator.SetBool("Walking", playerHasHorizontalSpeed);
}
public void Flipsprite()
{
bool playerhashorizontalspeed = Mathf.Abs(myRigidBody.velocity.x) > Mathf.Epsilon;
if (playerhashorizontalspeed)
{
transform.localScale = new Vector2(Mathf.Sign(myRigidBody.velocity.x), 1f);
transform.rotation = new Vector2(Mathf.Sign(firePoint.transform.localScale.x), 1f);
}
}

The problem here is that the rotation is not effected by scaling. Only the relative scales and positions.
Also why are you using > Mathf.Epsilon and not simply > 0. As far as I understand you only need to check if it is not 0 ... using Mathf.Epsilon is such a small difference that it actually doesn't matter.
public void Move()
{
float controlThrow = CrossPlatformInputManager.GetAxis("Horizontal");
Vector2 playerVelocity = new Vector2(controlThrow * runSpeed, myRigidBody.velocity.y);
myRigidBody.velocity = playerVelocity;
bool playerHasHorizontalSpeed = Mathf.Abs(myRigidBody.velocity.x) > 0;
myAnimator.SetBool("Walking", playerHasHorizontalSpeed);
}
// store the last direction
int direction;
public void Flipsprite()
{
bool playerhashorizontalspeed = Mathf.Abs(myRigidBody.velocity.x) > 0;
if (playerhashorizontalspeed)
{
// update the direction
direction = Mathf.Sign(myRigidBody.velocity.x);
transform.localScale = new Vector2(direction, 1f);
}
}
Then when you are shooting multiply the direction also with direction
private IEnumerator FireContinuously()
{
while (true)
{
GameObject laser = Instantiate(bullet, firePoint.position, firePoint.rotation);
laser.GetComponent<Rigidbody2D>().velocity = new Vector2(projectileSpeed * direction, 0);
yield return new WaitForSeconds(projectileFiringPeriod);
}
}
a small hint:
If you make the type of
public RigidBody2D bullet
and drag in the according prefab again than you don't need to use GetComponent but could directly use
var laser = Instantiate(bullet, firePoint.position, firePoint.rotation);
laser.velocity = ...

Related

How to rotate object towards target smooth slowly ? The object is not rotating facing the target

The goal in the end is to rotate the object when he start moving so the object will facing towards the target he is moving to and also that the laser that coming out from the object eye will be facing the same target.
The object that i want to rotate is at first at position 0,0,0 because the object is a child. the player is holding the object by hand. Then the object is getting throw with animation towards a target.
The object is moving to the target but now i want the object to rotate also smooth slowly to the target in this case i set the rotation duration 1 second. and i see that the object rotation is changing but not facing the target.
This screenshot show the object while it's still in the player hand at position 0,0,0
Then the object get throw and start moving to the target at this time the object rotation change :
The object that throw have a child transform the eye and from the eye a laser beam should be coming out and then i want to make that the object will rotate towards the target so the laser from the eye will be facing the target.
I marked the eye with a small red circle :
In this screenshot i marked the target far away, the laser in green is not facing the target and also the eye is not facing the target. the laser should come out the eye and the whole object should facing the target so the laser also should be facing the target with the eye.
This screenshot is of the object before running the game the eye is facing forwards with the object. this is just to show that the eye is aligned with the object facing forward.
This script is attached to my player and make the object to be thrown to the target and also should make the object to be rotating towards the target :
The throw part that make the object move to the target is working fine but the rotating part is not :
private IEnumerator AnimateRotationTowards(Quaternion transformRot, Quaternion targetRot, float dur)
{
float t = 0f;
while (t < dur)
{
transformRot = Quaternion.Slerp(transformRot, targetRot, t / dur);
yield return null;
t += Time.deltaTime;
}
transformRot = targetRot;
}
Also i see that making transformRot = targetRot; for some reason there is a small message say unnecessary assignment not sure why.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThrowObject : MonoBehaviour
{
public Transform objectToThrow;
public Transform target;
public Transform objectToThrowParent;
public float throwingSpeed;
public float waitAtTargetTime;
public float distanceToStopFromTarget;
public bool go = false;
public AnimationCurve animationCurve;
private Animator anim;
private bool startThrowAnimationOnce = true;
private bool reParent = false;
private bool startMovingBack = false;
private void Start()
{
anim = GetComponent<Animator>();
}
private void Update()
{
if (anim != null && startThrowAnimationOnce)
{
anim.SetTrigger("Throw");
startThrowAnimationOnce = false;
}
if (go)
{
objectToThrow.parent = null;
StartCoroutine(Throw());
StartCoroutine(AnimateRotationTowards(objectToThrow.rotation, target.rotation, 1f));
go = false;
}
if (reParent)
{
objectToThrow.position = objectToThrowParent.position;
}
if (startMovingBack)
{
if (Vector3.Distance(objectToThrow.position, objectToThrowParent.position) >= 0.1f)
{
float step = 5 * Time.deltaTime;
objectToThrow.position = Vector3.MoveTowards(objectToThrow.position, objectToThrowParent.position, step);
}
else
{
objectToThrow.position = objectToThrowParent.position;
objectToThrow.parent = objectToThrowParent;
objectToThrow.localPosition = new Vector3(0, 0, 0);
}
}
}
public void ThrowEvent()
{
go = true;
}
IEnumerator Throw()
{
while(Vector3.Distance(objectToThrow.position, target.position) >= distanceToStopFromTarget)
{
objectToThrow.position = Vector3.MoveTowards(
objectToThrow.position,
target.position,
throwingSpeed * Time.deltaTime
);
yield return null;
}
yield return new WaitForSeconds(waitAtTargetTime);
startMovingBack = true;
}
private IEnumerator AnimateRotationTowards(Quaternion transformRot, Quaternion targetRot, float dur)
{
float t = 0f;
while (t < dur)
{
transformRot = Quaternion.Slerp(transformRot, targetRot, t / dur);
yield return null;
t += Time.deltaTime;
}
transformRot = targetRot;
}
}
This script is attached to the object eye and fire the laser :
The target in this script is the same target as in the ThrowObject script :
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System;
using UnityEngine;
public class Hovl_DemoLasers : MonoBehaviour
{
public List<Transform> targets;
public GameObject FirePoint;
public Camera Cam;
public float MaxLength;
public GameObject[] Prefabs;
private Ray RayMouse;
private Vector3 direction;
private Quaternion rotation;
[Header("GUI")]
private float windowDpi;
private int Prefab;
private GameObject Instance;
private Hovl_Laser LaserScript;
private Hovl_Laser2 LaserScript2;
private bool rotateMouse = true;
private bool startLaser = true;
private float buttonSaver = 0f;
private Hovl_LaserDemo hovl_laserDemo;
private float maxDistance = 0;
private int closestIndex = 0;
void Start()
{
if (Screen.dpi < 1) windowDpi = 1;
if (Screen.dpi < 200) windowDpi = 1;
else windowDpi = Screen.dpi / 200f;
Counter(0);
}
void Update()
{
//Enable lazer
if (Input.GetMouseButtonDown(0))
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
rotateMouse = true;
}
if (Input.GetMouseButtonDown(1))
{
rotateMouse = false;
}
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
{
buttonSaver = 0f;
Counter(-1);
}
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
{
buttonSaver = 0f;
Counter(+1);
}
buttonSaver += Time.deltaTime;
if (startLaser)
{
rotateMouse = false;
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
hovl_laserDemo = Instance.GetComponent<Hovl_LaserDemo>();
startLaser = false;
}
if (targets != null)
{
maxDistance = Mathf.Infinity;
for (int i = 0; i < targets.Count; i++)
{
float distance = Vector3.Distance(gameObject.transform.position, targets[i].position);
if (distance < maxDistance)
{
maxDistance = distance;
closestIndex = i;
}
}
if (hovl_laserDemo != null)
{
float distance = Vector3.Distance(gameObject.transform.position, targets[closestIndex].position);
MaxLength = distance;
hovl_laserDemo.MaxLength = distance;
}
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, MaxLength))
{
RotateToMouseDirection(gameObject, targets[closestIndex].position);
}
else
{
RotateToMouseDirection(gameObject, targets[closestIndex].position);
}
}
if (Cam != null && rotateMouse)
{
RaycastHit hit;
var mousePos = Input.mousePosition;
RayMouse = Cam.ScreenPointToRay(mousePos);
if (Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
else
{
Debug.Log("No camera");
}
}
void OnGUI()
{
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change lazers!");
GUI.Label(new Rect(10 * windowDpi, 20 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button for shooting!");
}
void Counter(int count)
{
Prefab += count;
if (Prefab > Prefabs.Length - 1)
{
Prefab = 0;
}
else if (Prefab < 0)
{
Prefab = Prefabs.Length - 1;
}
}
void RotateToMouseDirection(GameObject obj, Vector3 destination)
{
direction = destination - obj.transform.position;
rotation = Quaternion.LookRotation(direction);
obj.transform.localRotation = Quaternion.Lerp(obj.transform.rotation, rotation, 1);
}
}
This is one situation where it is important to understand the difference between passing by value, or passing by reference. In your AnimateRotationTowards function, all of the parameters to that function are passed by value. Changes to those rotations will affect the local values within the function scope, but those are not the same values that get used in the scene.
What you probably want instead is a reference to some Transform object. If you assign a new rotation to that Transform, it will use that rotation in the scene.
It looks like this script component is attached to the GameObject that will be rotating. Is that right? If yes, you can set a new rotation by assigning a value to transform.rotation:
private IEnumerator AnimateRotationTowards(Quaternion transformRot, Quaternion targetRot, float dur)
{
float t = 0f;
while (t < dur)
{
transform.rotation = Quaternion.Slerp(transformRot, targetRot, t / dur);
yield return null;
t += Time.deltaTime;
}
transform.rotation = targetRot;
}
If you need to assign a rotation to some other GameObject, you can pass in a reference to that GameObject or its Transform and use that to assign the rotation.

unity rigidbody It's going up and bounces when is moving

I have a problem with rigidbody, This is a simple character controller script. the problem is i created some square floor tiles and each floor has mesh collider. soo when the character moving fast on thes floor tiles the charachter will going up a little bit or bounces when moving !! this is a image and a code of script
[]
public class character_controller : MonoBehaviour {
[Header("Speeds")]
public float move_speed;
public float move_smooth;
public float rotate_speed;
[Header("Physics")]
public float gravity_force = -10.0f;
[Header("Distances")]
public float ground_min_dis = 0.25f;
public float ground_max_dis = 100;
[Header("Layers")]
public LayerMask ground_layer;
[HideInInspector] public Rigidbody rb;
[HideInInspector] public Vector3 dir;
[HideInInspector] public Vector3 input;
[HideInInspector] public Vector3 input_smooth;
[HideInInspector] public bool move_to_direction;
[HideInInspector] public bool rotate_to_direction;
[HideInInspector] public bool can_move;
[HideInInspector] public bool is_on_ground;
private float ground_distance;
private RaycastHit ground_hit;
// method: start is called before the first frame update
void Start() {
rb = GetComponent<Rigidbody>();
can_move = true;
move_to_direction = true;
}
// method: update is called once per frame
void Update() {
move_input();
check_ground_distance();
}
// method: fixed update is called every fixed framerate frame
void FixedUpdate() {
if(
move_to_direction
) {
move();
}
}
// method: move input
private void move_input() {
input.x = Input.GetAxis("Vertical");
input.z = Input.GetAxis("Horizontal");
}
// method: move character
private void move() {
// input smooth for moving character smoothly
input_smooth = Vector3.Lerp(input_smooth, input, move_smooth * Time.deltaTime);
// get the forward facing direction of the character
var forward = Vector3.forward;
// get the left facing direction of the character
var right = Vector3.left;
// determine the direction
dir = (input_smooth.x * forward) + (input_smooth.z * right);
// normalize direction
if (
dir.magnitude > 1f
) {
dir.Normalize();
}
Vector3 target_position = rb.position + dir * move_speed * Time.deltaTime;
Vector3 target_velocity = (target_position - transform.position) / Time.deltaTime;
target_velocity.y = rb.velocity.y;
if(
can_move
) {
rb.velocity = target_velocity;
}
if(
input.magnitude > 0.01f
) {
// start rotate to direction
if(
rotate_to_direction == true
) {
start_rotate_to_direction(dir, rotate_speed);
}
}
}
// method: rotate character to direction
public void start_rotate_to_direction(
Vector3 dir,
float speed
) {
Vector3 forward;
Quaternion new_rotation;
forward = Vector3.RotateTowards(transform.forward, dir.normalized, speed * Time.deltaTime, 0.1f);
forward.y = 0;
new_rotation = Quaternion.LookRotation(forward);
transform.rotation = new_rotation;
}
// method: check ground distance
private void check_ground_distance() {
float distance;
Ray ray = new Ray(transform.position, Vector3.down);
// if the ray hit to the ground layer
if (
Physics.Raycast(ray, out ground_hit, ground_max_dis, ground_layer)
) {
if(
!ground_hit.collider.isTrigger
) {
distance = transform.position.y - ground_hit.point.y;
ground_distance = (float)System.Math.Round(distance, 2);
}
}
// check if character on the ground
if(
ground_distance <= ground_min_dis
) {
is_on_ground = true;
} else {
is_on_ground = false;
}
// apply force gravity when falling
if(
is_on_ground == false
) {
rb.AddForce(transform.up * gravity_force * Time.deltaTime, ForceMode.VelocityChange);
}
}}
Can you please read this manual page carefully?
I think, the page explains this phenomena (it is called ghost collision). Probably, your rigidbody hits to the border of mesh colliders just like described in manual.
Also, did you try to freeze motion along related axis by using inspector? It can be a quick solution.
I solved this problem by going into Edit > Project Settings > Physics from Physics tab you can set the Default Contact Offset value from 0.01 to 0.0001.

How can I make the NPC move only vertical and horizontal and not diagonal with Vector2/3.MoveTowards and how can I make the NPC move only by tile

So I was trying to make a game just for fun and to learn for future use. So I encountered this problem in making the enemy NPC. I want it to follow me or chase me but I want the NPC to only move horizontal and vertical and I want the NPC to move per tile as well just like my Player.
Here's the video of how it looks
https://www.youtube.com/watch?v=CB_vdt1Z3nA
and here's the NPC script
public class ChaseScript : MonoBehaviour
{
public float speed;
private GameObject player;
private Transform player_transform;
void Start()
{
player = GameObject.Find("Player");
}
void Update()
{
player_transform = player.GetComponent<Transform>();
transform.position = Vector3.MoveTowards(transform.position, player_transform.position, speed * Time.deltaTime);
}
}
Here's my player controller
public void InputMove()
{
if (!isMoving)
{
input.x = Input.GetAxisRaw("Horizontal");
input.y = Input.GetAxisRaw("Vertical");
if (input.x != 0) input.y = 0;
if (input != Vector2.zero)
{
playerAnimation.SetParameterValue(animator);
var movePos = transform.position;
movePos.x += input.x;
movePos.y += input.y;
FacingForward.transform.position = movePos;
if (IsWalkable(movePos))
StartCoroutine(Move(movePos));
}
playerAnimation.SetParameterValueisMoving(animator);
}
if (Input.GetKey(KeyCode.LeftShift))
{
moveSpeed = 6f;
animator.speed = 1.5f;
}
else
{
moveSpeed = 4f;
animator.speed = 1f;
}
}
IEnumerator Move(Vector3 movePos)
{
isMoving = true;
while ((movePos - transform.position).sqrMagnitude > Mathf.Epsilon)
{
transform.position = Vector3.MoveTowards(transform.position, movePos, moveSpeed * Time.deltaTime);
yield return null;
}
transform.position = movePos;
isMoving = false;
}
private bool IsWalkable(Vector3 movePos)
{
if (Physics2D.OverlapCircle(movePos, 0.1f, SolidObjectLayer | NPC) != null)
{
return false;
}
return true;
}
What I did to my Player to move per tile is I just add 1 to transform so It'll be a constant movement but I don't know how to apply it on the NPC with the Vector3.MoveTowards but if it's not possible to do then it's fine
Check if this could work (you can adapt it to your 2D case)
using UnityEngine;
public class ChaseOrthoScript : MonoBehaviour
{
public float speed;
private GameObject player;
private Transform player_transform;
bool isMoving = false;
void Start()
{
player = GameObject.Find("Player");
player_transform = player.GetComponent<Transform>();
transform.LookAt(player_transform.position);
}
void Update()
{
if (transform.InverseTransformPoint(player_transform.position).z > 0) {
transform.position += transform.forward * speed * Time.deltaTime;
isMoving = true;
} else {
if (isMoving) {
float angle = Vector3.Angle(transform.forward, player_transform.position - transform.position);
transform.Rotate(Vector3.up, Mathf.Sign(angle) * 90);
isMoving = false;
} else if (transform.InverseTransformPoint(player_transform.position).z <= 0) { //player is back
transform.Rotate(Vector3.up, 180);
}
}
}
}
note that the player_transform = player.GetComponent<Transform>(); is moved to the Start(). Usually you dont want GetComponents in an update as you need to get it only once. ALso its much cleaner to have a public GameObject player; variable in the script and attach the reference in the editor that the player = GameObject.Find("Player");. Usually you dont want scene elements found by a hardcoded magic value in your code.
Hope that helps.

Unity 3D Aerial movement and jumping problem

Aerial Movement Problem
I've followed a few tutorials and I've set up a decent base for a game, - basic player movement, entity animation, health, HUD UI, etc. - but I wanted to make the movement a bit smoother, less snappy, more physics-based, you get the gist. I made it a bit better and it definitely meets all the requirements for terrain-based movement (i.e: movement across physical surfaces - while the player is on the ground), but I want jumping to be a bit more dynamic, and I know what I want to do but I'm having trouble doing it.
Here's the issue:
If the player moves (regardless of whether sprintActive is toggled or not) and they jump after moving, the player gains speed in the air way too fast, and they can't move in any direction other than forward (relative to their rotation).
Here's the objective:
I set it up so the velocity is simply redirected to whatever direction is forward from the playerRB, but I think I would prefer if the velocity didn't immediately change direction, but rather gradually curve as the player tries to move a certain direction? I know I may be asking for a lot, but some advice on how to do this, or if I should try a different approach, would be very much appreciated.
Code used:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RFPSPlayerMovement : MonoBehaviour
{
public float speedForce;
public float jumpForce;
public float diveForce;
public Transform groundCheck;
public float groundDistance = 0.25f;
public LayerMask groundMask;
private Transform playerBody;
private Rigidbody playerRB;
private bool isGrounded;
private bool sprintActive = false;
private bool delay = false;
private float lateralSpeed;
private Vector3 velocity;
float xMov, zMov;
float xSpeed, zSpeed;
IEnumerator DelayTimer(float duration)
{
delay = true;
yield return new WaitForSeconds(duration);
delay = false;
}
void Start()
{
playerBody = GetComponent<Transform>();
playerRB = GetComponent<Rigidbody>();
}
void Update()
{
xMov = Input.GetAxisRaw("Horizontal") * Time.deltaTime;
zMov = Input.GetAxisRaw("Vertical") * Time.deltaTime;
if(Input.GetKey(KeyCode.LeftShift))
{
sprintActive = true;
}
else
{
sprintActive = false;
}
if(Input.GetKey(KeyCode.W))
{
Movement(0, speedForce);
}
if(Input.GetKey(KeyCode.S))
{
Movement(0, -speedForce);
}
if(Input.GetKey(KeyCode.A))
{
Movement(-speedForce, 0);
}
if(Input.GetKey(KeyCode.D))
{
Movement(speedForce, 0);
}
if(Input.GetKey(KeyCode.Space))
{
if(delay == false)
{
if(isGrounded)
{
StartCoroutine(DelayTimer(0.05f));
Jump(jumpForce);
}
}
}
}
void FixedUpdate()
{
velocity = playerRB.velocity;
lateralSpeed = new Vector2(playerRB.velocity.x, playerRB.velocity.z).magnitude;
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if(isGrounded)
{
velocity = new Vector3(
xMov + (float) (playerRB.velocity.x * 0.90),
playerRB.velocity.y,
zMov + (float) (playerRB.velocity.z * 0.90)
);
}
else
{
velocity.x = (float) (playerBody.forward.x * lateralSpeed);
velocity.y = playerRB.velocity.y;
velocity.z = (float) (playerBody.forward.z * lateralSpeed);
}
playerBody.eulerAngles = new Vector3(0, playerBody.eulerAngles.y, 0);
playerRB.velocity = velocity;
}
void Movement(float xAmount, float zAmount)
{
if(sprintActive)
{
xSpeed = (float) (xAmount * 2);
zSpeed = (float) (zAmount * 2);
}
else
{
xSpeed = xAmount;
zSpeed = zAmount;
}
playerRB.AddRelativeForce(new Vector3(xSpeed, 0, zSpeed), ForceMode.Impulse);
}
void Jump(float yAmount)
{
playerRB.AddRelativeForce(new Vector3(0, yAmount, 0), ForceMode.Impulse);
}
}

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