Unity 2D - Change the sprite by script DOESN'T WORK - unity3d

I have multiple images then push them into "Sprite[] sprites".
I create a gameobjectPrefab and add Rigidbody2d + Box Colider 2d + SpriteRenderer.
I want to Instantiate number of gameobjectPrefabs equal to the number of other sprites.
But it doesn't work, plz teach me the problem. The Sprites don't change:
public Sprite[] sprites;
public GameObject diamondPrefab;
void Start()
{
CreateDiamondsListSprites();
}
void CreateDiamondsListSprites()
{
for (int i = 0; i < sprites.Length; i++)
{
var go = diamondPrefab;
go.GetComponent<SpriteRenderer>().sprite = sprites[i];
listAllDiamondsFromSpritesList.Add(go);
// Here is sample : i add to list<gameOject> to use later
Instantiate(listAllDiamondsFromSpritesList[index],listLocationPoint[index]);
}
}

Set the sprite on the instantiated gameObject, after instantiation
void CreateDiamondsListSprites()
{
for (int i = 0; i < sprites.Length; i++)
{
var go = Instantiate(diamondPrefab,listLocationPoint[index]);
go.GetComponent<SpriteRenderer>().sprite = sprites[i];
listAllDiamondsFromSpritesList.Add(go);
}
}

Related

How to enlarge a ragdoll in game - Unity

I have a ragdoll. I want to increase the scale of this ragdoll in game mode. But when I increase the scale ragdoll' bones mingle and drool. How can i prevent this from happening? Related pictures below.
Normal Scale
3x Scale
Welcome to StackOverflow. After a quick search on Google and I've found an answer for you:
http://answers.unity.com/answers/1556521/view.html
TL;DR: joints calculate anchor only on start, but are never updated later. To make them update later, just reassign them
Transform[] children;
private Vector3[] _connectedAnchor;
private Vector3[] _anchor;
void Start()
{
children = transform.GetComponentsInChildren<Transform>();
_connectedAnchor = new Vector3[children.Length];
_anchor = new Vector3[children.Length];
for (int i = 0; i < children.Length; i++)
{
if (children[i].GetComponent<Joint>() != null)
{
_connectedAnchor[i] = children[i].GetComponent<Joint>().connectedAnchor;
_anchor[i] = children[i].GetComponent<Joint>().anchor;
}
}
}
private void Update()
{
for (int i = 0; i < children.Length; i++)
{
if (children[i].GetComponent<Joint>() != null)
{
children[i].GetComponent<Joint>().connectedAnchor = _connectedAnchor[i];
children[i].GetComponent<Joint>().anchor = _anchor[i];
}
}
}
Just make sure you do this reassign only when needed as it will hurt your performance...

RayCast2D ignor hitting own Collider

Board.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Board : MonoBehaviour
{
public Transform m_emptySprite;
private int m_height = 14;
private int m_width = 6;
// number of rows where we won't have grid lines at the top
public int m_header = 8;
// Start is called before the first frame update
void Start()
{
DrawEmptyCells();
}
void DrawEmptyCells()
{
for (int y = 0; y < m_height - m_header; y++)
{
for (int x = 0; x < m_width; x++)
{
Transform tile;
tile = Instantiate(m_emptySprite, new Vector3(x, y, 0), Quaternion.identity) as Transform;
tile.name = "Tile ( x = " + x.ToString() + " ,y = " + y.ToString() + ")";
tile.transform.parent = transform;
}
}
}
}
Tile.cs
public class Tile : MonoBehaviour
{
private Vector2[] adjacentDirections = new Vector2[] { Vector2.up, Vector2.down, Vector2.left, Vector2.right };
void OnMouseDown()
{
GetAllAdjacentTiles();
}
private GameObject GetAdjacent(Vector2 castDir)
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, castDir);
if (hit.collider != null)
{
print(hit.collider.gameObject.name);
return hit.collider.gameObject;
}
return null;
}
private List<GameObject> GetAllAdjacentTiles()
{
List<GameObject> adjacentTiles = new List<GameObject>();
for (int i = 0; i < adjacentDirections.Length; i++)
{
adjacentTiles.Add(GetAdjacent(adjacentDirections[i]));
}
return adjacentTiles;
}
}
I have tried to use the code above to detect tiles in all 4 directions but when I click on a tile I just get the name of the tile that was clicked.
Each tile has the Tile Script and a BoxCollider2D attached, why is it not printing all 4 tiles surrounding the current tile?
By default for Physics2D you are hitting your own collider the Raycast starts in.
To solve this go to the Physics2D Settings via Edit &rightarrow; Project Settings &rightarrow; Physics2D and disable the option
Queries Start In Colliders
Enable this option if you want physics queries that start inside a Collider 2D to detect the collider they start in.

How to resize all particles from a particle system?

I'm trying to dynamically resize particles using a slider, as well as change their colour.
Particles are used to display datapoints in a 3D scatterplot. I'm using this code: https://github.com/PrinzEugn/Scatterplot_Standalone
private ParticleSystem.Particle[] particlePoints;
void Update () {
pointScale = sizeSlider.value;
for (int i = 0; i < pointList.Count; i++) {
Quaternion quaternion = Camera.current.transform.rotation;
Vector3 angles = quaternion.eulerAngles;
// Set point color
particlePoints[i].startColor = new Color(angles.x, angles.y, angles.z, 1.0f);
particlePoints[i].transform.localScale = new Vector3(pointScale, pointScale, pointScale);
}
}
The issue is that there's no transform method for Particles, and changing the "startColour" doesn't change anything.
The API states that "The current size of the particle is calculated procedurally based on this value and the active size modules."
What does that mean, and how can I change the size of the particles ?
Thanks to previous answers I managed to get this working:
In the PlacePrefabPoints method I add every instantiated prefab to a List, and I add a listener to the slider, which looks like this:
void changedPointSize(){
pointScale = sizeSlider.value;
for (int i = 0; i < objects.Count; i++) {
objects[i].transform.localScale = new Vector3(pointScale, pointScale, pointScale);
}
}
Thanks all !
I just had a look at PointRenderer.cs -> CreateParticles and PlacePrefabPoints give a good hint what has to be changed.
So I guess you would simply change the scale values
foreach (var point in particlePoints)
{
Quaternion quaternion = Camera.current.transform.rotation;
Vector3 angles = quaternion.eulerAngles;
// Set point color
point.startColor = new Color(angles.x, angles.y, angles.z, 1.0f);
point.startSize = sizeSlider.value;
}
and than re-call
GetComponent<ParticleSystem>().SetParticles(particlePoints, particlePoints.Length);
it is questionable though if you really would do this in Update. I would rather do it in sizeSlider.onValueChanged to only do it when neccesarry (you could even make a certain treshold that has to be changed before updating the view) but well for the color there might be no other option than doing it in Update but atleast there I would use a Threshold:
privtae ParticleSystem ps;
// I assume you have that referenced in the inspector
public Slider sizeSlider;
// flag to control whether system should be updated
private bool updateSystem;
privtae void Awake()
{
ps = GetComponent<ParticleSystem>();
}
private void OnEnable()
{
// add a listener to onValueChanged
// it is secure to remove it first (even if not there yet)
// this makes sure it is not added twice
sizeSlider.onValueChanged.RemoveListener(OnsliderChanged());
sizeSlider.onValueChanged.AddListener(OnsliderChanged());
}
private void OnDisable()
{
// cleanup listener
sizeSlider.onValueChanged.RemoveListener(OnsliderChanged());
}
private void OnSliderChanged()
{
foreach (var point in particlePoints)
{
point.startSize = sizeSlider.value;
}
// do the same also for the instantiated prefabs
foreach(Transform child in PointHolder.transform)
{
child.localScale = Vecto3.one * sizeSlider.value;
}
updateSystem = true;
}
private Quaternion lastCameraRot;
public float CameraUpdateThreshold;
private void Update()
{
if(Quaternion.Angle(Camera.current.transform.rotation, lastCameraRot) > CameraUpdateThreshold)
{
foreach (var point in particlePoints)
{
Quaternion quaternion = Camera.current.transform.rotation;
Vector3 angles = quaternion.eulerAngles;
// Set point color
point.startColor = new Color(angles.x, angles.y, angles.z, 1.0f);
}
lastCameraRot = Camera.current.transform.rotation;
updateSystem = true;
}
if(!updateSystem) return;
updateSystem = false;
ps.SetParticles(particlePoints, particlePoints.Length);
}

Unity3d Sprite change with prefabs

Ive a question about how to change spirte images during runtime for a bunch of objects.
So i made a tiny racer 2d game, and therefore you can choose differend themes. You have this option in an integraded menu (not a seperate scene).
My question:
Can i switch the sprites easy during the runtime? Ive made prefabs for each track element - and i changed the sprites of those prefabs, but the change only gets visible, after the scene is reloaded. So i would need to avoid this.
Has someone a solution or a hint how i could do that?
Thanks in advance!
Code:
public class Background_Controller : MonoBehaviour {
public Camera mainCamera;
public Color colorNormal;
public GameObject[] Prefabs;
public Sprite[] normalSprites;
public Sprite[] tronSprites;
// Use this for initialization
void Awake () {
SwitchBackgroundFunction();
}
public void SwitchBackground(string Theme)
{
switch(Theme)
{
case "GreenHell":
PlayerPrefs.SetString("Theme", "Normal");
break;
case "NeonCity":
PlayerPrefs.SetString("Theme", "Tron");
break;
}
SwitchBackgroundFunction();
}
private void SwitchBackgroundFunction()
{
int prefabCount = Prefabs.Length;
if (PlayerPrefs.GetString("Theme") == "Normal")
{
mainCamera.backgroundColor = colorNormal;
for (int i = 0; i <= prefabCount - 1; i++)
{
Prefabs[i].GetComponent<SpriteRenderer>().sprite = normalSprites[i];
}
}
if (PlayerPrefs.GetString("Theme") == "Tron")
{
mainCamera.backgroundColor = Color.black;
for (int i = 0; i <= prefabCount - 1; i++)
{
Prefabs[i].GetComponent<SpriteRenderer>().sprite = tronSprites[i];
}
}
}
// Update is called once per frame
void Update () {
}
}
You can do something along the following lines to swap in a sprite from within your resources folder during runtime.
Sprite spr;
spr = Resources.Load<Sprite>("mysprite"); //insert name and file path to sprite within Resources folder
GetComponent<SpriteRenderer>().sprite = spr;

scaling issue on click event

I am developing a 2D game in Unity. I've created a character panel in that to let player select different character. In panel, there are thumbnails for different character. By tapping on a particular character thumbnail, the player can view that character. The original scale of thumbnail is 1, and when player taps on thumbnail, the scale get doubles. All is fine till this. but issue is that whenever player taps on thumbnail its scale gets double. But i want to limit it to once only. I've used flag to stop scaling, But still issue is there. After flag it stops scaling, but now player can click on multiple character simultaneously. I am copying snippet here.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class ViewCharacter : MonoBehaviour {
[SerializeField]
private GameObject TempCharacterHolder ,TempCharacter, TempCharacterText, TempCharacterPrice;
// Use this for initialization
void Start () {
for (int i = 0; i < ShoppingManager.instance.ShoppingList.Count; i++) {
if (i == TheGameController.instance.GetSelectedCharacter ()) {
PlayerPrefs.SetInt ("CharacterScaled" + i, 1);
} else {
PlayerPrefs.SetInt ("CharacterScaled" + i, 0);
}
}
}
public void ViewCharacterFunc()
{
int ClickedCharacter = int.Parse (TempCharacterText.GetComponent<Text> ().text);
foreach (var characters in ShoppingManager.instance.ShoppingList) {
if (string.Equals (characters.CharacterName, TempCharacterText.GetComponent<Text> ().text)) {
if (PlayerPrefs.GetInt("CharacterScaled"+characters.CharacterName)==0) {
ShoppingManager.instance.IncreaseScale (TempCharacter, TempCharacterHolder);
for (int i = 0; i < ShoppingManager.instance.ShoppingList.Count; i++) {
if (i == ClickedCharacter) {
PlayerPrefs.SetInt ("CharacterScaled" + i, 1);
} else {
PlayerPrefs.SetInt ("CharacterScaled" + i, 0);
}
}
}
} else {
Color clr = characters.Character_Holder.GetComponent<Image> ().color;
clr.a = 1;
characters.Character_Holder.GetComponent<Image> ().color = clr;
Vector3 TempVector = characters.CharaacterObject.GetComponent<RectTransform> ().localScale;
TempVector.x = 1f;
TempVector.y = 1f;
characters.CharaacterObject.GetComponent<RectTransform> ().localScale = TempVector;
}
}
}
}
If I understand your question correctly, your characters scale numerous times when you click on them instead of scaling once.
If that's the case, I'd suggest controlling that with a bool:
bool hasTouched = false;
void OnMouseDown()
{
ShoppingManager.instance.Message.SetActive (false);
foreach (var characters in ShoppingManager.instance.ShoppingList) {
Color clr = characters.Character_Holder.GetComponent<Image> ().color;
clr.a = 1;
characters.Character_Holder.GetComponent<Image> ().color = clr;
if (!hasTouched) //if we havent touched
{
Vector3 TempVector = characters.CharaacterObject.GetComponent<RectTransform> ().localScale*Time.deltaTime;
TempVector.x = 1.0f;
TempVector.y = 1.0f;
characters.CharaacterObject.GetComponent<RectTransform> ().localScale = TempVector;
hasTouched = true; //then we scale it, and we have touched it
}
}