Using RPC to spawn my player - unity3d

In my project, I have two prefabs - One with a first person camera, and another one stripped of all it's first person components such as the mouselook, input controller, camera, and so on. My ultimate goal is to spawn my prefab with the camera on it and sending an rpc to spawn the dummy prefab on all other clients to sync up with my first person prefab. The problem I'm facing is when I try to send the rpc from my first person prefab's PhotonView, the rpc doesn't get called on other clients because the PhotonView id doesn't exist on other clients yet.
The following code is located on my NetworkManager script on an empty game object in the hierarchy.
void OnJoinedRoom(){
GameObject MyPlayer = (GameObject) Instantiate (FPSPlayer,spawnPoint.transform.position, spawnPoint.transform.rotation);
FPSPlayerPhotonView = MyPlayer.transform.root.gameObject.GetPhotonView();
int id = PhotonNetwork.AllocateViewID ();
FPSPlayerPhotonView.viewID = id;
FPSPlayerPhotonView.RPC("SpawnMyPlayerAsRemote", PhotonTargets.OthersBuffered,id, spawnPoint.transform.position, spawnPoint.transform.rotation);
}
[PunRPC]
void SpawnMyPlayerAsRemote(int id, Vector3 pos, Quaternion rot){
GameObject MyRemotePlayer = (GameObject)Instantiate (RemotePlayer, pos,rot);
RemotePlayerPhotonView = MyRemotePlayer.transform.root.gameObject.GetPhotonView();
RemotePlayerPhotonView.viewID = id;
}

This method is tested and will work.
What I suggest you do is create an empty player with NetworkView.
Create this player via PhotonNetwork.Instantiate so it will be instantiated inside all clients.
Check you are the owner of the networkview.
If you are, create all the client sided essentials (FPS Camera etc...).
If you aren't, create the dummy.
EDIT: I was wrong on the RPC part.

Related

İn Unity Photon Network , Learn who did the bullet come from?

I make a game using photon network . 2 actors are shooting at each other and when the bullet is formed on the stage I want to know who the bullet came from. I can send player id in bullet Instantiate and I can find player in for loop but i don't think it's true.
Is there better than this method?
Code
void Shoot()
{
var part = GetComponentInChildren<ParticleSystem>();
part.Play();
float angle = cc.isFacingRight ? 0f : 180f;
GameObject gameob = PhotonNetwork.Instantiate("Bullet", firingPoint.position, Quaternion.Euler(new Vector3(0f, 0f, angle)),0, null);
}
You can simply use photonView.Owner, since the bullet is a networked object. Alternatively, you can use photonView.IsMine to check if the client running the check owns the bullet, instead of comparing owners.
(The photonView instance comes from assuming your bullet script extends MonoBehaviourPun instead of MonoBehaviour)

How to properly use prefabs from AsssetBundles?

I've recently encountered AssetBundles and tried to implement it in my project. I have a pretty simple game where controlling a character you should collect coins. I created the AssetBundle where I made prefabs and put everything from the game scene (background, player, terrain, etc...) into the AssetBundle. However, when loading objects from the bundle to the game scene, despite having the same size and transform parameters in the inspector, they are bigger than their original prefabs when starting a game. When it comes to the loaded character, not only is it ten times the size of the original but it also needs to be readjusted in script dependencies during the game to control it with a joystick. In terms of prefab size discrepancy, I think it has something to do with the loading screen as everything that comes out of the bundle is scaled to its size (see Fig.1) but I don't know why it happens nor how to fix it.
The script which loads prefabs:
public class LoadAssetBundles : MonoBehaviour
{
AssetBundle loadedAssetBundle;
public string path;
public string assetName;
void Start()
{
LoadAssetBundle(path);
InstantiateObjectFromBundle(assetName);
}
void LoadAssetBundle(string bundleUrl)
{
loadedAssetBundle = AssetBundle.LoadFromFile(bundleUrl);
}
void InstantiateObjectFromBundle(string assetName)
{
var prefab = loadedAssetBundle.LoadAsset(assetName);
Instantiate(prefab);
}
}
Try setting your prefab root (the most outer gameObject) scale to 1, them rescale your sprites inside it.
If you have a CanvasScaler on your canvas, the canvas scale will probably be lower than 1, something small like: 0.02321f, your object seems to have a high scale like 107.f or something, this may be the cause of the discrepancies.
When instantiating, try passing a parent transform (where you want to place your prefab) and change the bool instantiateInWorldSpace (on/off) and see how it affects your prefab.
public static Object Instantiate(Object original, Transform parent, bool instantiateInWorldSpace);
Check docs: https://docs.unity3d.com/ScriptReference/Object.Instantiate.html

Unity comparing gameobjects

I'm learning Unity by trying to do things and then when ofc failing (Because that's life about XD) then I'll try to find some scripts to learn from.
I was trying to make a smooth platformer controller and then ran into a video from Brackeys
I'm having trouble understanding this line of code:
if (colliders[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
(Full script can be found here: https://github.com/Brackeys/2D-Character-Controller/blob/master/CharacterController2D.cs)
It's that line 54 the one that is making me have problems.
if (colliders[i].gameObject != gameObject)
What is he comparing? The first one is the gameobject attached to the collider but the second one is the default class, can someone explain what is he trying to do here?
Notice that Monobehvaiour inherits from component. So it has access to all its properties gameObject, transform ..etc. Check component documentation
So in the snippet
if (colliders[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
you are comparing the specific array's object (colliders[i].gameObject) with the current monobehaviour the code is running in (gameObject or this.gameObject).
In a class, you can access all the public and protected members it inherits from skypping the this keyword, as it can be understood you refer to the current instance by default.
Hope that makes sense.

Updating values in a component in instantiated gameobject in unity

Hi i have a Robot Prefab, with a NPC script that is linked to dialogue sentences.
I am retrieving the information about dialogues (using a loader script) from a server API, and then instantiating both the robot gameobject and the sentences. For example for instantiating the gameobject:
GameObject newObject = GameObject.Instantiate(Resources.Load("prefabs/" + item.gameObject.name) as GameObject, parentProps);
newObject.transform.localPosition = new Vector3(loaded.x, loaded.y, loaded.z);
newObject.transform.localEulerAngles = new Vector3(0, 90f, 0);
However, i do not know how to access the dialogue and update it. Could someone tell me how to update the instantiated value of the sentences here (marked it with red arrows on the image below)?
May be a basic question, but am new. Thanks!
You can create a public function in Npc class and call it after you instantiated it.
GameObject newObject = GameObject.Instantiate(Resources.Load("prefabs/" + item.gameObject.name) as GameObject, parentProps);
newObject.transform.localPosition = new Vector3(loaded.x, loaded.y, loaded.z);
newObject.transform.localEulerAngles = new Vector3(0, 90f, 0);
newObject.GetComponent<Npc>().UpdateDialog();
On your Robot GameObject use GetComponent to get the NPC script object. Then you are able to modify the values. Make sure that the visibility of your variables is either public or has getters/setters.

Unity UNET- Can't spawn object with client authority

I have a problem where I can't spawn the selected object from clients. It works perfectly when the action is performed by the host, but not when a client attempts it. When a client attempts it, I get the following error: "SpawnWithClientAuthority player object is not a player". This is quite confusing as it works perfectly when it's performed by the host.
The code for this particular part is the following:
private void updateAppearance(GameObject newObject)
{
Destroy(appearance);
hiderModel.SetActive(false);
int newObjectNum = propNames.IndexOf(newObject.name);
activePropIndex = newObjectNum;
Debug.Log(newObjectNum);
newObject = (GameObject)Instantiate(props[newObjectNum], playerCam.gameObject.transform);
newObject.transform.localPosition = new Vector3(0, getObjectHeight(newObjectNum), 0);
NetworkServer.SpawnWithClientAuthority(newObject, gameObject); <--- This part gives the error
appearance = newObject;
appearance.transform.localPosition = new Vector3(0, appearance.transform.localPosition.y, 0);
}
The object to spawn has localAuthority set and has a network transform on it.
The object is registered as a spawnable object and it is the instantiated prefab that I am passing to the SpawnWithClientAuthority method. As far as I have read, this should allow the function to work, but unfortunately it doesn't.
Any ideas on how to fix this?
Thanks in advance
It works perfectly when the action is performed by the host, but not when a client attempts it
Because ONLY SERVER can spawn objects across the network.
Wrap your code to [Command] to execute it on server.