Texture load using string to int replace issue - c#

The issue according to my debug log is that my ints counts with no problem however the int to string conversion continues to apply to the original value not the updated counter on runtime. (there are some unused private's here for testing) & the frame values are all good.
a screen shot of my debug log: http://c2n.me/39GlfuI - as you can see the counter increases but 'frame' doesn't.
Hopefully this is self explanatory
using UnityEngine;
using System.Collections;
public class imagecycle : MonoBehaviour
{
public string Startingframe;
private string Nextframe;
private int framecomp = 0;
private int frameint;
private int framestep = 1;
private int maxframe = 119;
private string framestring;
// Use this for initialization
void Start ()
{
Nextframe = ("frame_000");
frameint = 20; // currently adding one to this and resetting on update
}
// Update is called once per frame
void Update ()
{
frameint += framestep;
//Converts framestring to int of frameint -updating frame
framestring = frameint.ToString();
Debug.Log (frameint);
// replaces loaded texture recourse with frame string:
Nextframe = Nextframe.Replace ("000", framestring);
// Loads texture into Currentframe:
Texture Currentframe = Resources.Load (Nextframe) as Texture;
// Applies texture:
renderer.material.mainTexture = Currentframe;
Debug.Log (Currentframe);
if (frameint > 119)
{
frameint = 1;
}
}
void LateUpdate()
{
}
}

that is because in first your next frame is "frame_000" so the replace method will replace 000 with 21 as you can see but after that your nextFrame variable is "frame_21" so there is no "000" in your string so your replace method wont do anything so nextFrame will stay at frame_21
Nextframe = Nextframe.Replace ("000", framestring); wont do anything after the first replace because its string doesnt conatins 000

Ah many thanks, so it was my understanding of the replace function that was incorrect, I assumed it would reset to frame_000 on on each update. Many thanks guys.
And yeah i'll try making it more efficient.
Also ,sorry I can't vote up yet; not enough 'rep'.

Related

Why is the private int variable in this c# program not updating?

Here's the program:
[SerializeField] ARPointCloudManager mArPointCloudManager;
private int numPointsUpdated = 0;
// Start is called before the first frame update
void Start()
{
UpdateTextPlanes();
mArPointCloudManager.pointCloudsChanged += onPointCloudsChanged;
}
// Update is called once per frame
void Update()
{
UpdateTextPlanes();
}
void onPointCloudsChanged(ARPointCloudChangedEventArgs args)
{
foreach (var pointCloudUpdated in args.updated)
{
numPointsUpdated += 1;
}
}
private void UpdateTextPlanes()
{
PlaneText.SetText(" Point Clouds Updated = " + numPointsUpdated);
}
The values of the private int variable remains zero & i don't understand why it's happening. I tried making the variable static & placing it at the top of my class before everything else but that didn't make any difference. I've searched around a lot but i can't find either solutions or explanations. I'm a beginner.
The problem was resolved when i wired all of the variables correctly in my unity project.

How can I change one material texture in an array?

How can I change one material in an array?
I've imported a Daz figure into unity, all of the materials are stored in an array for the figure.
I'm trying to change the texture of the Irises with the click of a button.
The code below does change the material but only on the first material in the array. I've attempted to alter the code to change the Irises, but I have been unable to.
{
//Component
private Renderer _rendereyes;
//Game Object
public GameObject eyes;
//etc
public Object[] texEyes;
public int texID;
// Start is called before the first frame update
void Start()
{
//Get Component
_rendereyes = eyes.GetComponent<Renderer>();
//Change eye tex
string texPath = "Textures";
texEyes = Resources.LoadAll(texPath, typeof(Texture2D));
}
public void SetEyeTexture()
{
if (texID < texEyes.Length - 1)
{
texID++;
}
else
{
texID = 0;
}
_rendereyes.material.SetTexture("_DiffuseMap",(Texture2D)texEyes[texID]);
}
Here is the 2nd iteration of the code which is my attempt to alter the Irises texture.
{
//Component
private Renderer[] _rendereyes;
//Game Object
public GameObject eyes;
//etc
public Object[] texEyes;
public int texID;
// Start is called before the first frame update
void Start()
{
//Get Component
_rendereyes = eyes.GetComponent<Renderer[]>();
//Change eye tex
string texPath = "Textures";
texEyes = Resources.LoadAll(texPath, typeof(Texture2D));
}
public void SetEyeTexture()
{
if (texID < texEyes.Length - 1)
{
texID++;
}
else
{
texID = 0;
}
_rendereyes[15].material.SetTexture("_DiffuseMap",(Texture2D)texEyes[texID]);
}
What is the best way to change the Irises texture?
First of all in general avoid using Resources at all. (See Best practices -> Resources)
Don't use it!
Then if you use it and in general I would be more specific and do
public Texture2D[] texEyes;
and then
texEyes = Resources.LoadAll<Texture2D>(texPath);
or rather simply drag and drop them into the slots via the Inspector
And finally
GetComponent<Renderer[]>
makes no sense. You always want to either get a single component or use GetComponents.
However, it sounds like you actually have only one single object with one single Renderer and want to stick to
_rendereyes = eyes.GetComponent<Renderer>();
or directly make it
[SerializeField] private Renderer _rendereyes;
and drag the object into the slot in the Inspector.
And then rather access the according index from Renderer.materials.
And then you have a little logical mistake in your SetEyeTexture method.
You do
if (texID < texEyes.Length - 1)
{
texID++;
}
which might result in texID = texEyes.Length which will be out o bounds since in c# all indices go from 0 to array.Length - 1.
Your code should rather look like
public void SetEyeTexture()
{
// Simple modulo trick to get a wrap around index
texID = (++texID) % texEyes.Length;
// Note that according to your screenshot the Material "Irises" is at index 14 not 15!
_rendereyes.materials[14].SetTexture("_DiffuseMap", texEyes[texID]);
}

Unity Question: How Can I Switch From One prefab To Another With GetAxis?

I want to bind the up and down arrow keys to cycle through different sprites upon being pressed. If one end is reached, it would loop back to the first sprite. I've tried using the following code:
public class PhaseChanger : MonoBehaviour
{
// saved for efficiency
[SerializeField]
public GameObject prefabMoon0;
[SerializeField]
public GameObject prefabMoon1;
[SerializeField]
public GameObject prefabMoon2;
[SerializeField]
public GameObject prefabMoon3;
[SerializeField]
public GameObject prefabMoon4;
// needed for new phase
GameObject currentPhase;
bool previousFramePhaseChangeInput = false;
/// <summary>
/// Start is called before the first frame update
/// </summary>
void Start()
{
currentPhase = Instantiate<GameObject>(prefabMoon0);
}
/// <summary>
/// Update is called once per frame
/// </summary>
void Update()
{
// change phase on up arrow or down arrow
if (Input.GetAxis("ChangePhase") > 0)
{
// only change phase on first input frame
if (!previousFramePhaseChangeInput)
{
previousFramePhaseChangeInput = true;
// Save current position and destroy current phase
Destroy(currentPhase);
// instantiate next phase
if (currentPhase = prefabMoon0)
{
currentPhase = Instantiate(prefabMoon1);
}
else if (currentPhase = prefabMoon1)
{
currentPhase = Instantiate(prefabMoon2);
}
else if (currentPhase = prefabMoon2)
{
currentPhase = Instantiate(prefabMoon3);
}
else if (currentPhase = prefabMoon3)
{
currentPhase = Instantiate(prefabMoon4);
else
{
// no phase change input
previousFramePhaseChangeInput = false;
}
}
}
}
When I attach the script to my main camera and run it, I'm able to make a single change with the up arrow, and then nothing else happens on subsequent presses.
I feel like I'm really close to making this work, but I also may being doing the whole thing inefficiently. Help would be much appreciated, thanks!
Also: I know I said sprites in my post and am sharing a script that calls on prefabs. I didn't know how to approach this using just the sprites without making a prefab for each. Is it possible to do this without separate prefabs for each sprite?
Problems
First of all you are using assignments
currentPhase = XY
where you should be using
currentPhase == XY
The reason why it still compiles is the implicit conversion operator for UnityEngine.Object -> bool. Basically your assigning equals writing
currentPhase = XY;
if(currentPhase)
It won't work like this either way because you are using Instantiate to create a new clone of a prefab which will of course have a different reference than the original prefab it was cloned from.
So even if your checks where looking like
if(currentPhase == XY)
they will ever be true.
Solution
Instead of checking for reference equality I would rather store all prefabs/instances in an array
public GameObject[] phases;
and then simply have an int index for this array so you can simply move to the next element from the array by increasing the index.
private int currentPhase;
And you can increase it and make it wrap around using e.g.
currentPhase = (currentPhase + 1) % phases.Length;
so it will always grow from 0 up to phases.Length - 1 and then start over from 0 again.
And then I don't know the exact requirements of your use case but I would suggest to rather not all the time use Instantiate and Destroy but rather have already all the objects as instances under your object and just (de)actívate them!
you could do this like e.g.
public GameObject[] phases;
private int currentPhase;
private void Awake ()
{
Init();
}
private void Update ()
{
if (Input.GetAxis("ChangePhase") > 0)
{
if (!previousFramePhaseChangeInput)
{
previousFramePhaseChangeInput = true;
NextPhase();
}
}
else
{
previousFramePhaseChangeInput = false;
}
}
// Disables all phases except the first one and sets the current index to 0
private void Init()
{
for(var i = 1; i < phases.Length; i++)
{
phases[i].SetActive(false);
}
phases[0].SetActive(true);
currentPhase = 0;
}
// Disables the current phase and enables the next one
// wraps around at the end of the array
public void NextPhase()
{
phases[currentPhase].SetActive(false);
// increase the counter and wrap around at the end of the array
currentPhase = (currentPhase + 1) % phases.Length;
phases[currentPhase].SetActive(true);
}
If you still want to Instantiate the objects because having them already in the scene is no option (for whatever reason) you could do it right before calling Init like e.g.
public GameObject[] phasePrefabs;
private GameObject[] phases;
private void Awake ()
{
var amount = phasePrefabs.Length;
phases = new GameObject [amount];
for(var i = 0; i < amount; i++)
{
phases[i] = Instantiate(phasePrefabs[i]);
}
Init();
}
Though as said I would prefer to already have them right away as this is way less error prone ;)

Wrong number converting int to string c#

I have simple coin counter, in 2d Unity game. But It's count one coin as 2. I think that it's because of wrong converting int to string.
public GameObject coin; // Gameobject with coin
public Text CoinCounter; // Text with counter that shows in game
private float TotalCounter = 0; // Float for counting total amount of picked up coins
{
TotalCounter = Convert.ToInt32((CoinCounter.text)); // Converting text counter to Numbers
}
private void Update()
{
TotalCounter = Convert.ToInt32((CoinCounter.text)); // Updating Counter evry frame update
Debug.Log(TotalCounter); // Showing Counter in Console
}
private void OnTriggerEnter2D(Collider2D collision)
{
TotalCounter = (TotalCounter + 1); // adding 1 to total amount when player touching coin
CoinCounter.text = TotalCounter.ToString(); // Converting to Text, and showing up in UI
coin.SetActive(false); // Hiding coin
}
So, in Debug Log it's showing right Total amount, but in UI, It's Showing wrong number. As example, When Total Amount is 1 it's showing 2 etc.
It's better to write your convertor code into the trigger void , after that check it ; this might be happened because of update function, try like that and check again: `
public GameObject coin;
public Text CoinCounter;
private float TotalCounter = 0;
private void Update()
{}
private void OnTriggerEnter2D(Collider2D collision)
{
TotalCounter = (TotalCounter + 1);
Debug.Log(TotalCounter);
CoinCounter.text = TotalCounter.ToString();
Debug.Log(CoinCounter.text);
coin.SetActive(false);
}
`
You don't have to do it in Update but only when you actually change it.
The method you are looking for is probably int.TryParse
you should use int for amounts (unless will you have values like 1.5 coins later)
Than you execute your code everytime it collides ... with anything. You should only collide with a coin instead. Either use tags or compare with the referenced value in your case
public GameObject Coin; // Gameobject with coin
public Text CoinCounter; // Text with counter that shows in game
private int _totalCounter = 0; // Int for counting total amount of picked up coins
// I guess it's supposed to be Start here
void Start()
{
// Converting text counter to Numbers
int.TryParse(CoinCounter.text, out _totalCounter);
}
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject != Coin) return;
// later this should probably rather be
//if(collision.gameObject.tag != "Coin") return
_totalCounter += 1; // adding 1 to total amount when player touching coin
CoinCounter.text = _totalCounter.ToString(); // Converting to Text, and showing up in UI
Coin.SetActive(false); // Hiding coin
// later this should probably rather be
//collision.gameObject.SetActive(false);
}
Problem was not in converting, trigger worked twice. Need check if the coin is enabled before disabling it and adding to the coin counter. Eg:
if (coin.activeSelf)
{
coin.SetActive(false);
Debug.Log("Object is not active ");
TotalCounter += 1;
Debug.Log("Total Counter + :" + TotalCounter);
CoinCounter.text = TotalCounter.ToString();
Debug.Log("Text after +:" + CoinCounter.text);
}

Unity - Particle system - Particle count

Does any know if Unity has a way to count how many particles have been emitted by a particle system? So I could check to see if there has been an emission, like:
public ParticleSystem mySystem;
private int currentParticleCount;
private int lastParticleCount;
void Start () {
lastParticleCount = mySystem.getEmissionCount();
}
void Update () {
currentParticleCount = mySystem.getEmissionCount();
if(currentParticleCount>lastParticleCount) {
DoStuff();
}
lastParticleCount = currentParticleCount;
}
You can use ParticleSystem.particleCount to return the current number of particles. If that's not giving you the proper amount of particles, use the ParticleSystem.GetParticles function since that returns just the current number of alive particles. Below is an example for both of them:
private ParticleSystem ps;
// Use this for initialization
void Start()
{
ps = GetComponent<ParticleSystem>();
}
// Update is called once per frame
void Update()
{
Debug.Log("Particles Count: " + ps.particleCount);
Debug.Log("Particles Alive Count: " + GetAliveParticles());
}
int GetAliveParticles()
{
ParticleSystem.Particle[] particles = new ParticleSystem.Particle[ps.particleCount];
return ps.GetParticles(particles);
}
The exact feature that you are asking for is not build it, BUT:
You can know the current particles displayed by the system, so you can make a counter that acumulates the number, or if you know the "displaying time" you can do the maths.
Knowing the current particles:
ParticleSystem.particleCount https://docs.unity3d.com/ScriptReference/ParticleSystem-particleCount.html

Categories