Reputation: 1305
I have been trying to add little things on top of the tutorials Unity supplies and I am confused about how to get this certain mechanic to work.
When my player shoots it shoots in the direction of the mouse. When I run a client and host on my computer so that 2 people are connect for testing I get weird results.
I have both of my players shooting in the correct direction but when I am moving my mouse on one of the clients I see that my blue circle (which represents where the bullets will be spawned) is moving when that client is not focused, meaning I am not currently clicked on that client and when I am moving my mouse I see the blue circle moving on the client I am not focused on which I am not sure if my friend down the street was to test this would it cause errors.
Here are 2 screenshots of my Scene/Game view to get a better visual : Pic 1 - Pic 2
I ended up using Network Transform Child on my parent GameObject for one of my children GameObjects that helps spawn the location of the bullets but still the visual look from my Scene tab makes me worry about the accuracy of bullets being spawned.
Here is my shooting code that :
public class PlayerShooting : NetworkBehaviour
{
public GameObject bulletPrefab;
public GameObject fireSpot;
public float bulletSpeed;
public Transform rotater;
public Camera cam;
void Update()
{
// Only run the below code if this is the local player.
if (!isLocalPlayer)
{
return;
}
// Rotate based on the location of the mouse our spot to shoot bullets.
Vector3 dir = cam.ScreenToWorldPoint (Input.mousePosition) - rotater.position;
float angle = Mathf.Atan2 (dir.y, dir.x) * Mathf.Rad2Deg;
rotater.rotation = Quaternion.AngleAxis (angle, Vector3.forward);
// When we hit spacebar
if(Input.GetKeyDown(KeyCode.Space))
{
// Fire some bullets.
CmdFire ();
}
}
// Something the client is wanting to be done and sends this "command" to the server to be processed
[Command]
public void CmdFire ()
{
// Create the Bullet from the Bullet Prefab
var bullet = (GameObject)Instantiate (bulletPrefab, fireSpot.transform.position, Quaternion.identity);
// Add velocity to the bullet
bullet.GetComponent<Rigidbody2D>().velocity = (fireSpot.transform.position - rotater.position).normalized * bulletSpeed;
// Spawn the bullets for the Clients.
NetworkServer.Spawn (bullet);
// Destroy the bullet after 2 seconds
Destroy(bullet, 4.0f);
}
}
My movement script :
public class Movement : NetworkBehaviour {
void Update()
{
if (!isLocalPlayer)
{
return;
}
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 3.0f;
var y = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;
transform.Translate(x, y, 0f);
}
}
Upvotes: 0
Views: 109
Reputation: 9821
This will continue to be a problem if you'd like to run multiple instances of unity games on the same machine. If you go into Edit > Project Settings > Player, there is a Run in Background option under Resolution and Presentation. If you have this checked, both instances of the game will receive updated mouse positions per frame from Input.mousePosition
(Keep in mind Input.GetKeyDown
will only register to the focused instance of the game so there's some inconsistency here). If you don't have that check box selected, your game instance will pause when not focused (I'm guessing you don't want this if you're working with a client/host networking paradigm).
There are a few ways you can work around this. The ideal way to test a networked game would be to have a unique PC for each instance of the game. If that's not an option, you can add some checks to ensure the mouse is over the window. As long as the two windows don't overlap you can do that by checking the position against the screen info:
bool IsMouseOverWindow()
{
return !(Input.mousePosition.x < 0 ||
Input.mousePosition.y < 0 ||
Input.mousePosition.x > Screen.width ||
Input.mousePosition.y > Screen.height);
}
You can then use this to decide, in your Update()
, whether or not you want to update rotator.rotation
.
Another option would be to implement MonoBehaviour.OnApplicationFocus
. You can then enable/disable things (like updating rotations based on mousePosition
) in response to that event. The cleanest solution would be to have a clear way for your systems to ask "is my window focused". You can make a class like this:
public class FocusListener : MonoBehaviour
{
public static bool isFocused = true;
void OnApplicationFocus (bool hasFocus) {
isFocused = hasFocus;
}
}
Make sure you have one of these somewhere in your game and then anything can check by looking at FocusListener.isFocused
.
Upvotes: 1