A SpriteRenderer is not displaying the sprite when set the second time - unity3d

I have a cell prefab in which I have a GameObject with SpriteRenderer. I am instantiating multiple instances of a prefab and feeding a sprite for every instance. The first cell instance is displaying the given sprite but the second one is not.
Here I am creating two instances of a Cell and feeding the Cell with a sprite from mIconManager:
private void PopulateCells()
{
for (var i = 0; i < 2; i++)
{
GameObject goPrefab = Instantiate(goRawPrefab, CalculateCellPosition(i), Quaternion.identity, trBoard);
CellController cellController = goPrefab.GetComponent<CellController>();
cellController.FillContent(mIconManager.getSprite(i), i);
}
}
This is a snippet from CellController script attached to a Cell:
private void Awake()
{
mIcon = GameObject.Find("IconSprite").GetComponent<SpriteRenderer>();
mCardBg = GameObject.Find("CardBg").GetComponent<SpriteRenderer>();
}
public void FillContent(Sprite sprite, int index)
{
mSprite = sprite;
mIcon.sprite = mSprite;
}
This is my Cell prefab:
When I run the code, the second instance of a prefab is not getting the sprite.
I checked the first prefab's SpriteRenderer in the inspector while the game is running, and it said anchovies for the sprite - the one I gave via FillContent() method. Interestingly, the second prefab's SpriteRenderer component shows EMPTY sprite.
First Prefab's SpriteRenderer while game is running:
Second Prefab's SpriteRenderer while game is running:
Am I missing something? I searched through the internet and found some posts saying "SpriteRenderer is not loading sprites the second time" but they were not answered and the ones that were answered didn't solve my problem.
P.S. I also tried setting the SAME sprite for both instances of the Cell prefab - still no success.
P.S.2. I logged the sprites that are given to the both instances of the Cell prefab and they were not null or empty. I even did Debug.Log(mIcon.sprite) which both instances logged the name of sprites I provided.
Edit:
Logging when giving the same sprite to both instances:
public void FillContent(Sprite sprite, int index)
{
Debug.Log("hop, spriteName : " + sprite + ", prefabIndex : " + index);
mSprite = sprite;
mIcon.sprite = sprite;
}

Try Filling It with the same sprite twice the code seems fairly normal
This will Help me debug it al lil more ie.
private void PopulateCells()
{
for (var i = 0; i < 2; i++)
{
GameObject goPrefab = Instantiate(goRawPrefab, CalculateCellPosition(i), Quaternion.identity, trBoard);
CellController cellController = goPrefab.GetComponent<CellController>();
cellController.FillContent(mIconManager.getSprite(1), i);
}
}

Okay, it turns out the problem was not related to the SpriteRenderer. SpriteRenderer was working as expected. However, the way I got a reference to the SpriteRenderer was not correct.
In CellController, I was getting a reference to the SpriteRenderer with GameObject.Find..., the thing is it was not giving me a reference to a instantiated prefab clone, but to the first prefab clone.
private void Awake()
{
mIcon = GameObject.Find("IconSprite").GetComponent<SpriteRenderer>();
mCardBg = GameObject.Find("CardBg").GetComponent<SpriteRenderer>();
}
Instead, I used tranform.Find and everything worked as expected.

Related

How to enable a player's prefab for everyone in the game?

I use Playfab and Photon for my Unity project. I added some weapons, shields and body types to my player prefab and disabled all of them (except the head). I store which weapon, shield and body type the user have, and pull them from playfab when the player logs in. But the problem is, I can see my own weapon, shield and body but cannot see other player's. I can only see their heads! I assume that it is because when other user joins the scene, their prefab instantiates with PhotonNetwork but SetActive method is working for individuals, not for the server. Here is my code:
public override void OnJoinedRoom()
{
s = "PlayerArmature(Clone)/";
if(PFLogin.prefabName=="Female"){
gameObject = PhotonNetwork.Instantiate(playerPrefabFemale.name, new Vector3(73, 22, 34), Quaternion.identity, 0,null);
s = "PlayerArmatureF(Clone)/";
s += "FemaleCharacterPolyart/";
view = playerPrefabFemale.GetComponent<PhotonView>();
}else{
gameObject = PhotonNetwork.Instantiate(playerPrefab.name, new Vector3(73, 22, 34), Quaternion.identity, 0,null);
s += "MaleCharacterPolyart/";
view = playerPrefab.GetComponent<PhotonView>();
}
GameObject body = GameObject.Find(s+PFLogin.body);
GameObject cloak = GameObject.Find(s+PFLogin.cloak);
GameObject shield = GameObject.Find(s+"root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l/weapon_l/"+PFLogin.shield);
GameObject weapon = GameObject.Find(s+"root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/weapon_r/"+PFLogin.weapon);
body.SetActive(true);
cloak.SetActive(true);
shield.SetActive(true);
weapon.SetActive(true);
if (view.IsMine)
{
view.RPC("ShowMesh", RpcTarget.AllBuffered, s);
}
}
void ShowMesh(string s)
{
GameObject body = GameObject.Find(s+PFLogin.body);
GameObject cloak = GameObject.Find(s+PFLogin.cloak);
GameObject shield = GameObject.Find(s+"root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l/weapon_l/"+PFLogin.shield);
GameObject weapon = GameObject.Find(s+"root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/weapon_r/"+PFLogin.weapon);
body.SetActive(true);
cloak.SetActive(true);
shield.SetActive(true);
weapon.SetActive(true);
}
PFLogin is a static class which stores static variables(body&weapon etc) that are assigned with playfab responses.
So my question is how can I call SetActive(true) such that everyone see others bodys(or other things).
At first I've tried without RPC and all I see was heads without bodies in the screen, now I've tried with RPC but nothing changed. It could be my lack because I am very new to all of this.
I would try to use the isMine to make every prefab active:
//at the beginning public PhotonView PV;
public void Awake()
{
PV = Gameobject.GetComponent<PhotonView>();
}
if (!PV.isMine)
{ Prefab.gameobject.SetActive(true) }
I hope it helps, I have never done it like you did, so I am

Instatiated objects from the same prefab share a position?

I'm starting a simple JRPG: generating a party from a group of prefabs, then moving each into position by changing their transform. But seeing a strange one where 3 goblins spawned from the same prefab are moving to exactly the same position. The other objects instantiated from different objects are moving correctly.
In the player, I can move the goblins by changing their transform, and they are separate. However the prefab itself is changing position to match the 'last' goblin spawned
Any hints? Am I somehow instantiating them to a common object?
Objects created and positioned in PartyManager:
public bool playerParty = true;
public GameObject[] party=new GameObject[4];
// Start is called before the first frame update
void Start()
{
for (int i=0; i<party.Length; i++){
GameObject character = Instantiate(party[i],this.gameObject.transform);
}
positionCharacters();
}
void positionCharacters(){
float facing = -1.0f;
if(playerParty) facing=1.0f;
for (int i=0; i<party.Length; i++){
party[i].transform.localPosition = new Vector3(-0.3f*i*facing, -0.05f*i,-0.1f*i);
print(party[i]+" moved to "+party[i].transform.localPosition);
}
}
First of all you don't seem to be storing references to the instantiated characters, GameObject character just goes out of scope immediately. If you put three references to the same object into GameObject[] party you shouldn't be surprised only the last set position is used.

Unity - Set player position after loading scene

I am Trying to set player position after loading a scene. The program runs ok sometimes, but sometimes it places the player in the wrong position.
This is a video showing this strange behaviour: https://youtu.be/MFl9P3taV0Y
This is the code:
public class IniciaHeroi : MonoBehaviour
{
public GameObject GM;
private int startPosition;
void Awake()
{
startPosition = GM.GetComponent<StartScene>().startPosition;
if(startPosition == 1)
{
transform.position = new Vector3(119,4.67f,36);
transform.GetComponent<HeroiMovimento>().rot = -30;
Debug.Log("StartPosition1: " + transform.position);
}
if(startPosition == 2)
{
transform.position = new Vector3(49,13.8f,167);
transform.GetComponent<HeroiMovimento>().rot = 100;
Debug.Log("StartPosition2: " + transform.position);
}
}
}
Debug log shows always the correct position but, as you can see in the video, something changes the position.
Can anyone point the correct way to do this?
The problem was the Character controller attached to my player. For some strange reason Character Controller do not change its own transform.position when i change player transform.position.
So the solution is to disable Character Controller before change player position and Enable it after the change.
Thanks!! Having the same issue, and took me so long to find this. Finally I was able to solve by using disabling the Controller and then enabling it:
example:
gameObject.GetComponent<CharacterController>().enabled = false;
gameObject.transform.position = new Vector3(-31, 1, -10);
gameObject.GetComponent<CharacterController>().enabled = true;

How to shoot particle like projectile?

I made a tank that shoot sphere balls on mouse click.
my C# script:
GameObject prefab;
// Use this for initialization
void Start () {
prefab = Resources.Load("projectile") as GameObject;
}
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0))
{
GameObject projectile = Instantiate(prefab) as GameObject;
projectile.transform.position = transform.position + Camera.main.transform.forward * 2;
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.velocity = Camera.main.transform.forward * 40;
}
}
in this script im shooting a mesh named projectile. But I want to shoot a particle ball and not a mesh. I already tried to change the particle to Orbparticle on script but no object was spawned. What im doing wrong?
No object was spawned because you probably don't have a resource called Orbparticle. Check if you have any errors when you run your script. If Resources.Load doesn't find the object you want by the path you gave it, it will give null, which probably why no object is being spawned.
If you want to shoot a particle instead of a mesh then what you need to do is set prefab to a GameObject you prepared ahead of time that has the ParticleSystem you want. I'd suggest against using Resources.Load for this.
1. Using Resources.Load.
Change your code to this so that it will alert you if it doesn't find the resource:
GameObject prefab;
// Use this for initialization
void Start () {
string name = "OrbParticle";
prefab = Resources.Load<GameObject>(name);
if (prefab == null) {
Debug.Error("Resource with name " + name + " could not be found!");
}
}
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0))
{
GameObject projectile = Instantiate(prefab) as GameObject;
projectile.transform.position = transform.position + Camera.main.transform.forward * 2;
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.velocity = Camera.main.transform.forward * 40;
}
}
Now in order for this to work you need a prefab called "OrbParticle" or whatever string you set the variable name to. Resources.Load looks for items in paths such as Assets/Resources. So you MUST have your "OrbParticle" prefab located in that Resources folder. Unless you have a specific reason for using Resources.Load, I strongly suggest you go with solution 2.
2. Ditching Resources.Load and using the Prefab directly.
Change your code to this:
public GameObject prefab;
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0))
{
GameObject projectile = Instantiate(prefab) as GameObject;
projectile.transform.position = transform.position + Camera.main.transform.forward * 2;
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.velocity = Camera.main.transform.forward * 40;
}
}
Then do this:
Create a new empty GameObject.
Attach a ParticleSystem to the GameObject.
Make a new prefab asset.
Drag and drop the newly created GameObject into a Prefab asset.
Drag and drop the the prefab into prefab field in your Monobehaviour (the object doing the shooting. It will have a prefab field in the Inspector. That's why we set prefab to be a public field).
If you continue having problems, look in Unity's Hierarchy to see if no object is being created at all. It might be the case that it is instantiating a GameObject but the GameObject is invisible for some reason or not instantiating in the location you expect.

how to randomly initialize particles system in different places of scene in unity3d

I recently tried asking this question but I realized it was not a sufficient question. In my game the player is a fire fighter learner and i want to broke out fire randomly in my game (like not predictable by player), but i did not know how to implement this.
So far i have done this but nothing goes good.(I have a empty object called t in unity which have 3 to 5 particles systems, and all are set to dont awake at start)
code is here :
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
public ParticleSystem[] particles;
public int numOn = 3;
public int j;
void Start() {
for (int i = 0; i < particles.Length - 1; i++) {
j = Random.Range(i + 1, particles.Length - 1);
ParticleSystem t = particles[j];
particles[j] = particles[i];
particles[i] = t;
}
for (j = 0; j < numOn; j++ )
{
particles[j].Play();
}
}
}
help will be appreciated :-)
You could try using prefabs. Create a game object in the editor that has any particle systems and scripts your fire objects need. Once it's good, drag the object from the hierarchy into your project. This will create a prefab (you can now remove it from the scene). Now, on your spawning script, add a field of type GameObject and drag the prefab you made before into it. Now, when you need to create one, just call Instantiate(prefabVar) to create a copy of your prefab.
Edit:
For your specific case, since you only want one fire to be instantiated in a random location, you could have your spawning script look something like this:
public Transform[] SpawnPoints;
public GameObject FirePrefab;
void Start() {
Transform selectedSpawnPoint = SpawnPoints[(int)Random.Range(0, SpawnPoints.Count - 1)];
Instantiate(FirePrefab, selectedSpawnPoint.position, selectedSpawnPoint.rotation);
}
This solution would allow for you to potentially spawn more than one fire object if you needed. An alternative would be if you will only ever have exactly one fire object in the scene at all. Instead of instantiating from a prefab, the object is already in the scene and you just move it to one of your spawn points at the start of the scene. An example script on the fire object itself:
public Transform[] SpawnPoints;
void Start() {
Transform selectedSpawnPoint = SpawnPoints[(int)Random.Range(0, SpawnPoints.Count - 1)];
transform.position = selectedSpawnPoint.position;
transform.rotation = selectedSpawnPoint.rotation;
}