The question is answered, right answer was accepted
Unet - similar spawn functions acting different, client scale not transferring
My game isn't complicated, I tried to learn Unet over a game jam weekend and couldn't finish, but im too stubborn. I've tried just about everything me and my resources could think of now, so fire away questions please!
I'll provide the code I'm working with, and the code that is working at the bottom.
Sooooo....
I'm trying to spawn a laser object for everyone when a player fires. This is done by a raycast the local player makes, filling up a list of start points and end points for a laser effect to be drawn, in this case its a textured quad.
To boot, I have objects already successfully spawning and destroying. NetworkServer.Destroy(block) and powerup work properly, as well as powerup instantiation and NetworkServer.Spawn(powerup). All players see these objects being created and destroyed, no duplicates.
Now for the laser...
The Host sees everything properly.
The Clients own laser scale doesn't retain from where it was set before spawn.
The Clients sees duplicates of the host laser.
Note: NetworkServer.Spawn(laserseg); is commented out and lasers still spawn for host????
Image: Host left, Client right
Here's code:
void LateUpdate()
{
if (!isLocalPlayer)
{
return;
}
Fire();
}
void Fire()
{
if (Input.GetButtonDown("Fire") && CanShoot && Energy >= EnergyPerShot)
{
ShootLaserRaycast();//generates list of positions via local raycast
Energy -= EnergyPerShot;
FireRateCoolDown();
for (int i = 1; i < LaserPoints.Count; i++)//getting all positions generated from local raycast
{
SendLaserEffect(LaserPoints[i - 1], LaserPoints[i]);//send positions pairs
}
}
}
public void SendLaserEffect(Vector3 pos1, Vector3 pos2)
{
//If we are the server, do the Rpc. If we are a client, do the Command.
if (!isServer)
{
Cmd_Effect(pos1, pos2);
}
else
{
Rpc_Effect(pos1, pos2);
}
}
[Command]
public void Cmd_Effect(Vector3 cmdpos1, Vector3 cmdpos2)
{
CreateEffect(cmdpos1, cmdpos2);
}
[ClientRpc]
public void Rpc_Effect(Vector3 rpcpos1, Vector3 rpcpos2)
{
CreateEffect(rpcpos1, rpcpos2);
}
void CreateEffect(Vector3 effectpos1, Vector3 effectpos12)
{
//create a new segments for the laser, LaserSegment is the stored prefab on this object
GameObject laserseg = Instantiate(LaserSegment, Vector3.zero, Quaternion.identity);
//position between points
Vector3 centerPos = (effectpos1 + effectpos12) / 2f;
laserseg.transform.position = centerPos;
//align effect rotation with points
Vector3 direction = effectpos12 - effectpos1;
direction = Vector3.Normalize(direction);
laserseg.transform.forward = direction;
//using a textured quad in place of a sprite, but the quad is naturally vertical, so I rotate it horizontal
laserseg.transform.eulerAngles = new Vector3(90, laserseg.transform.rotation.eulerAngles.y, laserseg.transform.rotation.eulerAngles.z);
//stretch the quad towards the points
Vector3 scale = new Vector3(1, 1, 1);
scale.y = Vector3.Distance(effectpos1, effectpos12);
laserseg.transform.localScale = scale;
//tell the server to spawn the piece of the laser
//NetworkServer.Spawn(laserseg);
}
Here the code of what is working, this gets called when the local raycast hits a block, it grabs a powerup id from the block, and spawns a powerup from a local list using the id.
[Command]
public void CmdDropPowerUp(GameObject block)
{
int id = block.GetComponent<Block>().PowerUpId;
if (id != 0)
{
GameObject powerup = Instantiate(GetComponent<LevelGen>().PowerUpDrops[id], block.transform.position, Quaternion.Euler(new Vector3(0f, 180f, 0f)));
NetworkServer.Spawn(powerup);
}
NetworkServer.Destroy(block);
}
[ClientRpc]
public void RpcDropPowerUp(GameObject block)
{
int id = block.GetComponent<Block>().PowerUpId;
if (id != 0)
{
GameObject powerup = Instantiate(GetComponent<LevelGen>().PowerUpDrops[id], block.transform.position, Quaternion.Euler(new Vector3(0f, 180f, 0f)));
NetworkServer.Spawn(powerup);
}
NetworkServer.Destroy(block);
}
Since this code works and the other doesn't, i'm at a complete loss for what to do. I'm wondering If both are wrong at this point.
Answer by some1s · Aug 02, 2017 at 09:26 AM
This was never going to be answered anyways like every other recent Unet question, Unet should just be abandoned.
I did find out why my two similar pieces of code acted so different in. Hopefully someone finds this useful as I couldn't submit to Ludem Dare 39 because of this.
Trying to store a public value from a script on a gameobject parameter specifically from a [ClientRpc] call doesn't work.
On my script, (id != 0) always returns 0 since the object in that list index is always created.
BUT Adding in NetworkServer.Spawn(powerup); Sends the correct object, and it doesn't get duplicated??
What is going on with Unet???
This Immediately caused anything else that tried to instantiate object to produce strange results. Like not spawning at all, not including the objects scale, duplicating.
[Command]
public void CmdDropPowerUp(GameObject block)
{
int id = block.GetComponent<Block>().PowerUpId;
if (id != 0)
{
GameObject powerup = Instantiate(GetComponent<LevelGen>().PowerUpDrops[id], block.transform.position, Quaternion.Euler(new Vector3(90f, 0f, 0f)));
NetworkServer.Spawn(powerup);
}
NetworkServer.Destroy(block);
}
[ClientRpc]
public void RpcDropPowerUp(GameObject block)
{
int id = block.GetComponent<Block>().PowerUpId;
if (id != 0)//THIS IS ALWAYS ZERO
{
GameObject powerup = Instantiate(GetComponent<LevelGen>().PowerUpDrops[id], block.transform.position, Quaternion.Euler(new Vector3(90f, 0f, 0f)));
NetworkServer.Spawn(powerup);//BUT THIS WILL SEND THE CORRECT BLOCK WITH NO DUPLICATES EVEN SO
}
NetworkServer.Destroy(block);
}
Follow this Question
Related Questions
Client Spawning Player Objects 0 Answers
Spawning GameObject on network, locally change it only on the client that spawned it. 0 Answers
[UNET] Spawn object on server BUT delete on your client 1 Answer
Mirror networking, weird behaviour with local scale 0 Answers
Fail to Connect to NetworkServer 1 Answer