- Home /
UNET Rotation of Child transform
I'm having serious trouble seeing the problem in my code that is preventing me from moving forward. I have coded this game to have the turrets on the tanks follow the mouse cursor of the player. The server turret faces the proper direction and it is represented on the client just fine. The client turret does calculate the rotation and fires projectiles in the proper direction, but does not rotate the turret transform. This is essentially the last step in my MVP for this prototype and I just can't see the problem. I need another set of eyes on the code to help me spot where I'm going wrong. Full disclaimer I am creating this project to teach myself UNET so if you spot a problem, or the problem I am having. I would very much appreciate a brief explanation as to what that problem is. Thank you for any help you can provide! I am including all relevant code below, the player class is basically a test-bed class for everything right now, I fully intend to split this class up into pieces once I have found this solution.
![using UnityEngine; using UnityEngine.Networking;
public enum Direction
{
NORTH,
EAST,
SOUTH,
WEST
}
// TODO: Client Rotation is not displayed on client, but is displayed on server
public class Player : NetworkBehaviour {
// from tutorial //
[SyncVar]
private Quaternion syncTurretRotation;
[SyncVar]
private float SPEED;
// from tutorial //
private bool moveUp = false; // Allow Movement Booleans
private bool moveDown = false;
private bool moveLeft = false;
private bool moveRight = false;
private bool facingNorth = true; // Facing Direction Booleans
private bool facingSouth = false;
private bool facingWest = false;
private bool facingEast = false;
private Direction direction = Direction.NORTH; // Direction of Next Movement
private float movementSpeed; // The speed the player is currently moving
public GameObject projectile; // The Projectile
private float force = 200.0f; // The force applied to the projectile
private Vector3 turretDir; // The direction the barrel is facing right now
const float NORMAL_SPEED = 0.5f;
private GameObject tankBarrel;
// This method only runs on the local player
// it doesn't run on any other instances of the player
// and it doesn't run on the server
public override void OnStartLocalPlayer()
{
base.OnStartLocalPlayer();
}
void Start ()
{
moveUp = false;
moveDown = false;
moveLeft = false;
moveRight = false;
facingNorth = true;
facingSouth = false;
facingWest = false;
facingEast = false;
direction = Direction.NORTH;
movementSpeed = NORMAL_SPEED;
tankBarrel = GameObject.FindGameObjectWithTag("tankTurret");
}
// Reduce Speed of the tank by a percentage of it's normal speed
[Client]
public void DiminishSpeed(float percent)
{
ReturnToNormalSpeed();
CmdSendSpeedData(movementSpeed *= percent);
}
// Increase speed of the tank by a percentage of its normal speed
[Client]
public void IncreaseSpeed(float percent)
{
ReturnToNormalSpeed();
CmdSendSpeedData(movementSpeed += (movementSpeed * percent));
}
// Return the tank to its normal speed
[Client]
public void ReturnToNormalSpeed()
{
movementSpeed = NORMAL_SPEED;
CmdSendSpeedData(movementSpeed);
}
[Command]
void CmdSendSpeedData(float speed)
{
SPEED = speed;
}
// Switch booleans for determining travel direction
private void ResetFacingDirection(Direction direction)
{
// Determine the last direction that
// the player was facing and reset that
// facing direction boolean.
switch (direction)
{
case Direction.NORTH:
facingNorth = false;
break;
case Direction.EAST:
facingEast = false;
break;
case Direction.SOUTH:
facingSouth = false;
break;
case Direction.WEST:
facingWest = false;
break;
default:
break;
}
}
// Rotate the tank in the direction of movement
private void RotateTank(Direction oldDirection, Direction newDirection)
{
// Determine the direction the player
// was last moving in (oldDirection)
// and rotate the tank in the direction
// the player is now moving in.
/*
* If oldDirection was Direction.NORTH
* and newDirection is Direction.EAST
* rotate the tank to the east from the North;
*
*/
switch (oldDirection)
{
case Direction.NORTH:
switch (newDirection)
{
case Direction.EAST:
// rotate to the east
Rotate(Vector3.forward, -90f);
break;
case Direction.SOUTH:
// rotate to the south
Rotate(Vector3.forward, 180f);
break;
case Direction.WEST:
// rotate to the west
Rotate(Vector3.forward, 90f);
break;
default:
break;
}
break;
case Direction.EAST:
switch (newDirection)
{
case Direction.NORTH:
// rotate to the north
Rotate(Vector3.forward, 90f);
break;
case Direction.SOUTH:
// rotate to the south
Rotate(Vector3.forward, -90f);
break;
case Direction.WEST:
// rotate to the west
Rotate(Vector3.forward, 180f);
break;
default:
break;
}
break;
case Direction.SOUTH:
switch (newDirection)
{
case Direction.EAST:
// rotate to the east
Rotate(Vector3.forward, 90f);
break;
case Direction.NORTH:
// rotate to the north
Rotate(Vector3.forward, 180f);
break;
case Direction.WEST:
// rotate to the west
Rotate(Vector3.forward, -90f);
break;
default:
break;
}
break;
case Direction.WEST:
switch (newDirection)
{
case Direction.EAST:
// rotate to the east
Rotate(Vector3.forward, 180f);
break;
case Direction.SOUTH:
// rotate to the south
Rotate(Vector3.forward, 90f);
break;
case Direction.NORTH:
// rotate to the north
Rotate(Vector3.forward, -90f);
break;
default:
break;
}
break;
default:
break;
}
}
// Process the input from the player
private void Processinput()
{
if (Input.GetKeyDown("w"))
{
// The tank should be facing North now
// if it is not
if (direction != Direction.NORTH)
{
// Determine which way to rotate the tank
RotateTank(direction, Direction.NORTH);
// Reset the facing direction booleans
ResetFacingDirection(direction);
// set the direction of next travel to North
direction = Direction.NORTH;
// set the facing direction boolean
facingNorth = true;
// allow the player to move north
moveUp = true;
}
else
{
moveUp = true;
}
}
if (Input.GetKeyDown("a"))
{
if (direction != Direction.WEST)
{
RotateTank(direction, Direction.WEST);
ResetFacingDirection(direction);
direction = Direction.WEST;
facingWest = true;
moveLeft = true;
}
else
{
moveLeft = true;
}
}
if (Input.GetKeyDown("s"))
{
if (direction != Direction.SOUTH)
{
RotateTank(direction, Direction.SOUTH);
ResetFacingDirection(direction);
direction = Direction.SOUTH;
facingSouth = true;
moveDown = true;
}
else
{
moveDown = true;
}
}
if (Input.GetKeyDown("d"))
{
if (direction != Direction.EAST)
{
RotateTank(direction, Direction.EAST);
ResetFacingDirection(direction);
direction = Direction.EAST;
facingEast = true;
moveRight = true;
}
else
{
moveRight = true;
}
}
// if no keys are pressed the tank should stop moving
// set the movement booleans to reflect this
if (Input.GetKeyUp("w"))
{
moveUp = false;
}
if (Input.GetKeyUp("a"))
{
moveLeft = false;
}
if (Input.GetKeyUp("s"))
{
moveDown = false;
}
if (Input.GetKeyUp("d"))
{
moveRight = false;
}
// Mouse Buttons
if (Input.GetMouseButtonDown(0))
{
CmdCreateProjectile();
}
if (Input.GetMouseButtonUp(0))
{
Debug.Log("You No Fire");
}
}
// Get the direction the tank barrel is currently facing
private Vector3 GetBarrelDirection()
{
return turretDir;
}
[Command]
private void CmdSetBarrelDirection(Vector3 dir)
{
turretDir = dir;
}
[Command]
private void CmdCreateProjectile()
{
GameObject clone;
Debug.Log("Fire 1");
clone = Instantiate(projectile, transform.localPosition + (0.4f * GetBarrelDirection()), Quaternion.identity) as GameObject;
clone.GetComponent<Rigidbody2D>().AddForce(GetBarrelDirection() * force);
// Spawn the bullet on the clients
NetworkServer.Spawn(clone);
}
[Client]
private void RotateBarrel()
{
//// Get the position of the transform in screen coordinates
Vector3 pos = Camera.main.WorldToScreenPoint(tankBarrel.transform.position);
//// Get the direction of the mouse from the transform
Vector3 dir = Vector3.Normalize(Input.mousePosition - pos);
CmdSetBarrelDirection(dir);
//// Get the angle
float angle = Mathf.Atan2(GetBarrelDirection().x, GetBarrelDirection().y) * Mathf.Rad2Deg;
angle *= -1;
//// Rotate the transform to face the mouse cursor
//// on this computer
tankBarrel.transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
CmdProvideRotationsToServer(tankBarrel.transform.rotation);
}
[Command]
void CmdProvideRotationsToServer(Quaternion turretRotation)
{
syncTurretRotation = turretRotation;
}
// Move the tank in the given direction
private void Move(Vector3 direction)
{
transform.localPosition += direction;
}
// Rotate the tank using the given rotation and angle
private void Rotate(Vector3 rotation, float angle)
{
transform.Rotate(rotation, angle);
}
void Update ()
{
if (!isLocalPlayer)
{
return;
}
Processinput();
// Move the tank in the direction the player has chosen
if (moveUp && facingNorth)
{
Move(new Vector3(0f, movementSpeed * Time.deltaTime, 0f));
}
else if (moveLeft && facingWest)
{
Move(new Vector3(-movementSpeed * Time.deltaTime, 0f, 0f));
}
else if(moveDown && facingSouth)
{
Move(new Vector3(0f, -movementSpeed * Time.deltaTime, 0f));
}
else if (moveRight && facingEast)
{
Move(new Vector3(movementSpeed * Time.deltaTime, 0f, 0f));
}
RotateBarrel();
}
}][1]
[1]: /storage/temp/76228-client.png
Hi, did you tried NetworkTransform component? Have a look at this: link text
@BeckStarDE The Player object is a NetworkTransform, and the turret object is a NetworkTransformChild attached to the Player Tank. Every instance of the game creates its own instance of the player. That player can only be controlled by the instance of the game the player was created in. The heirarchy is like this:
Player Object Prefab has NetworkTransform, NetworkIdentity, and NetworkTransformChild The turret object is passed into the NetworkTransformChild, and is a child object of the Tank object, which makes up the Player Object Prefab.
Not sure if its allowed on Unity Answers but I will include a version of the project in a link when I get home from work tonight if I am able.
Answer by freakysevenup · Aug 21, 2016 at 09:09 AM
Figured out my problem!!
Two things I was doing wrong:
First I changed the tankbarrel GameObject to a Transform Second in the RotateBarrel method I changed this line
float angle = Mathf.Atan2(GetBarrelDirection().x, GetBarrelDirection().y) * Mathf.Rad2Deg;
to
float angle = Mathf.Atan2(dir.x, dir.y) * Mathf.Rad2Deg;
getting the newly calculated direction and using that instead of the old direction, bone head move on my part for using the GetBarrelDirection method.
Hope this helps somebody in the future.
Your answer
Follow this Question
Related Questions
Why is my object rotation going back before rotating 1 Answer
Network rotation is laggy and slow 2 Answers
How can I align axis with quaternion.fromToRotation? 1 Answer
Lookat function working before implementing Multiplayer / Networking. 0 Answers
How to rotate/position the child object independently of the parent? 3 Answers