- Home /
UNet - The thing you want to instantiate is null
I try to instantiate an object in the game. It works perfectly for the host and other players can see it. For clients I just get error "The thing you want to instantiate is null". This script is attached to the Player gameObject with local-player network identity. The relevant code:
public void ActivateSkill(string skillName)
{
if (!isLocalPlayer)
{
return;
}
var command = (SkillDesc)skillDatabase.skills.Find(x => x.displayName == skillName);
ProcessCommand(command);
} [Command]
void CmdSpawnEffect(GameObject effect, float size, Vector3 pos)
{
GameObject obj = (GameObject)Instantiate(effect, pos, Quaternion.identity);
obj.transform.localScale = effect.transform.localScale * size;
Destroy(obj, 5f);
NetworkServer.Spawn(obj);
}
private void ProcessCommand(SkillDesc command)
{
foreach (var fx in command.VisualEffects)
{
switch (command.placement)
{
case SkillDesc.EffectPlacement.CenteredOnCharacter:
break;
case SkillDesc.EffectPlacement.CenteredOnFirstTarget:
break;
case SkillDesc.EffectPlacement.CenteredOnMouse:
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, float.PositiveInfinity, myLayerMask))
{
Vector3 pos = hit.point;
pos.y += 0.2f;
CmdSpawnEffect(fx.Particle_effect, fx.size, pos);
}
break;
case SkillDesc.EffectPlacement.CenteredOnTargets:
break;
}
Again, this works as intended on the server-client EDIT: I should add: The GameObject is retrieved from a ScriptableObject. SkillDatabase is a scriptableobject with a list skills containing the ScriptableObject skill. The scriptableobject skill contains the prefab. EDIT #2: The skilldatabase is instantiated on run-time, does that mean I have to register all the skills and their prefabs on run-time? Is that it? EDIT #3: Nvm, that didn't do shit. if (isClient) { for (int i = 0; i < skillDatabase.skills.Count; i++) { foreach (var obj in skillDatabase.skills[i].VisualEffects) { ClientScene.RegisterPrefab(obj.Particle_effect); } } }
Prefabs and object to be spawned must be registered.
You can do this in Network$$anonymous$$anager in editor or ClientScene by script.
Answer by Salmjak · Feb 15, 2016 at 10:59 AM
I solved it by sending the string name of the prefab to the [Command] and then using Resources.Load(string) to instantiate it.
[Command]
void CmdSpawnEffect(string effect, Vector3 pos, float size, float duration)
{
GameObject obj = (GameObject)Instantiate(Resources.Load(effect, typeof(GameObject)), pos, Quaternion.identity);
Destroy(obj, duration);
NetworkServer.Spawn(obj);
}
I would appreciate input on why my original method doesn't work.
Answer by BackslashOllie · May 07, 2016 at 08:02 AM
The reason your first method does not work is [Command] functions will only accept primitive parameters (like int, float, string).You cannot pass a GameObject to the host. So I think your string loading method is probably the better solution.
Actually, you can, but only GameObjects with a Network Identity.
Arguments to Remote Actions
The arguments passed to commands and ClientRpc calls are serialized and sent over the network. These arguments can be:
basic types (byte, int, float, string, UInt64, etc)
arrays of basic types structs containing allowable types
built-in unity math types (Vector3, Quaternion, etc)
NetworkIdentity
NetworkInstanceId
NetworkHash128
GameObject with a NetworkIdentity component attached
Arguments to remote actions cannot be subcomponents of GameObjects, such as script instances or Transforms. They cannot be other types that cannot be serialized across the network.
So what are your thoughts on the original posters question? I have tested similar behaviour and I get the same result when trying to pass the prefab as a parameter to the [Command]. When explicitly using the variable within the method the error is not thrown.