I am trying to get my Player prefabs leg and shoe to move "Forward" world space wise without my shoe on each leg rotating. I just want it pointing forward.
I have a player prefab. On the prefab I have a script, two gameobjects with a cylinder in each one acting as a "leg", and another two gameobject with a shoe model I made in each gameobject. the shoe gameobject is inside the leg gameobject. so for example it goes:
Player prefab
-> Right Leg Gameobject
-> Left Leg Gameobject
-> RightShoe Gameobject
-> Left Shoe Gameobject
and under each gameopbject is the respective models for the leg or shoe.
I have written code so that my player's legs "move"/"change rotation" to make it look like it's walking (I don't know any animation so this is the only way I know how). There is also code so that moving player is with AWSD and looking or rotating player is with the mouse, just like any typical FPS game, except my game in 3rd person.
My player's leg does move "forward" relative to world space so that is not an issue but hen I use the mouse to rotate or look in another direction (left or right), the players shoes also rotate left or right in place. At first I thought something was wrong with the shoes but I did not write any code to the shoes, I only wrote code for the legs. Since my legs were cylindrical, I did not notice the leg rotates too. I only found this out once I set my cylindrical legs to be more oblong or more egg shaped like.
is there a way I can make my shoes do the same "animation" as my leg but not make it rotate in place?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class PlayerController : NetworkBehaviour
{
public float speedH = 2.0f;
private float yaw = 0.0f;
public float WalkingTime; //timer for walking animation
public GameObject PlayerLeftLeg;
public GameObject PlayerRightLeg;
private float PlayerStatMenuTimer;
public GameObject PlayerStatsMenu;
public GameObject ThePlayer;
// Update is called once per frame
void Update () {
if (!isLocalPlayer)
{
return;
}
//keep track of time for player stat menu
//if not here than menua will show and hide like a thousand times when pressed once due to update reading code per frame
PlayerStatMenuTimer = PlayerStatMenuTimer + 1 * Time.deltaTime;
//moving player left right forward backward
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 50.0f;
var z = Input.GetAxis("Vertical") * Time.deltaTime * 50.0f;
transform.Translate(x, 0, z);
//rotating player or "Looking"
yaw += speedH * Input.GetAxis("Mouse X");
transform.eulerAngles = new Vector3(0.0f, yaw, 0.0f);
//if player is using WASD to move then do leg moving animation
//if not moving then set legs to be still and reset in standing position
//FYI: "transform.TransformVector(1,0,0)" was used instead of "Vector3.forward" was because
// vector3.forward is local space, so when i rotate player the sense of "forward" also changes, thus i needed
// a code that uses the world space, thus i used "transform.TransformVector(1,0,0)"
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D))
{
CmdWalk();
RpcWalk();
}
else
{
//if player not walking then reset
PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward);
PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward);
WalkingTime = 0;
}
//get hidden mouse pointer back and unlock
if (Input.GetKey(KeyCode.Escape))
{
Cursor.lockState = CursorLockMode.None;
}
//opens and closes stat menu
if (Input.GetKey(KeyCode.Return) && (PlayerStatMenuTimer>=1) && (PlayerStatsMenu.activeSelf==false))
{
Cursor.lockState = CursorLockMode.None;
PlayerStatsMenu.SetActive(true);
PlayerStatMenuTimer = 0;
//call the script "GetplayerStats" and call function "retrieceplayerstats"
var GetStats = GetComponent<GetPlayerStats>();
GetStats.RetrievePlayerStats();
}
else if (Input.GetKey(KeyCode.Return) && PlayerStatMenuTimer >= 1 && PlayerStatsMenu == true)
{
Cursor.lockState = CursorLockMode.Locked;
PlayerStatsMenu.SetActive(false);
PlayerStatMenuTimer = 0;
}
}
private void Awake()
{
//this code locks mouse onto center of window
//Screen.lockCursor = true;
Cursor.lockState = CursorLockMode.Locked;
}
//initiaztes when started up
void Start()
{
//calls script "SpawnItems" and function "RefreshItems" which will update the players items being shown
ThePlayer.GetComponent<SpawnItems>().RefreshItems();
}
//so COMMAND is for server to client
//it shows walking for local player
[Command]
void CmdWalk()
{
//timer
WalkingTime += Time.deltaTime;
//right leg stepping forward
if (WalkingTime > 0 && WalkingTime < .4)
{
PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * WalkingTime), transform.TransformVector(1, 0, 0));
PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * WalkingTime), transform.TransformVector(1, 0, 0));
}
//left leg stepping forward
if (WalkingTime > .4 && WalkingTime < 1.2)
{
PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x + (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0));
PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x - (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0));
}
//right leg stepping forward
if (WalkingTime > 1.2 && WalkingTime < 1.59)
{
PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0));
PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0));
}
//resetting
if (WalkingTime > 1.6)
{
PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward);
PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward);
WalkingTime = 0;
}
}
//so RPC is for Client to Server
//it shows walking for other client players
//https://stackguides.com/questions/53784897/unity-moving-player-leg-multiplayer
[ClientRpc]
void RpcWalk()
{
//timer
WalkingTime += Time.deltaTime;
//right leg stepping forward
if (WalkingTime > 0 && WalkingTime < .4)
{
PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * WalkingTime), transform.TransformVector(1, 0, 0));
PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * WalkingTime), transform.TransformVector(1, 0, 0));
}
//left leg stepping forward
if (WalkingTime > .4 && WalkingTime < 1.2)
{
PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x + (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0));
PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x - (60 * (WalkingTime - .8f)), transform.TransformVector(1, 0, 0));
}
//right leg stepping forward
if (WalkingTime > 1.2 && WalkingTime < 1.59)
{
PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(PlayerRightLeg.transform.rotation.x - (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0));
PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(PlayerLeftLeg.transform.rotation.x + (60 * (WalkingTime - 1.6f)), transform.TransformVector(1, 0, 0));
}
//resetting
if (WalkingTime > 1.6)
{
PlayerRightLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward);
PlayerLeftLeg.transform.rotation = Quaternion.AngleAxis(0, Vector3.forward);
WalkingTime = 0;
}
}
}
I have included the entire script for my player controller, all you need to focus on is the CMDWALK or RPC WALK, they are both the same piece of code.
if anyone needs more info on the leg movement world space, take a look at this link, it is another question I asked Unity Moving Player Leg Multiplayer
.rotation.xto get the x value. Don't mix Euler values with Quaternions. You could trytransform.localEulerAnglesinstead. - derHugotransform.Rotate(60*WalkingTime, 0, 0, Space.Self);and for a reset simplytransform.localRotation = Quaternion.Identity;- derHugo