- Home /
¿How Can I fill an array in runtime?
Hi folks having an issue that's driving me crazy. I'm working on a game mechanic in which you type a sequence of buttons and if that sequence matches with an existing one then you spawn a specific game object, kinda like a combo but not exaclty.
Here's the code with further explanation:
using System.Collections;
using System.Collections.Generic;
using System.Linq; // allows to compare contents of two arraws with a built-in function (SequenceEqual)
using UnityEngine;
public class BuilderMode : MonoBehaviour
{
public PlayerMovement playerMovement;
public bool onBuilderMode;
public bool arraysAreEquals;
public int[] testComboArray = { 1, 2, 3 };
public int[] testComboInputArray = new int[3];
//combo Inputs:
public KeyCode metal = KeyCode.Q;
public KeyCode spark = KeyCode.W;
public KeyCode ammo = KeyCode.E;
private int q_metalCode = 1;
private int w_sparkCode = 2;
private int e_ammoCode = 3;
public int comboSlotValue;
void Start()
{
onBuilderMode = false;
arraysAreEquals = false;
for (int i = 0; i < testComboInputArray.Length; i++)
{
testComboInputArray[i] = 0;
}
//for each (int i in testComboInputArray) print (i);
}
void Update()
{
StartBuilderMode();
CancelBuilderMode();
FillInputArray();
printComboKeysValues();
if (onBuilderMode == true && Input.GetButtonDown("Fire1"))
{
CheckArrays();
}
}
void StartBuilderMode()
{
if (Input.GetButtonDown("BuilderMode"))
{
onBuilderMode = true;
playerMovement.movementSpeed_magnitude = 0;
}
}
void CancelBuilderMode()
{
if (onBuilderMode == true && Input.GetButtonDown("Fire2"))
{
onBuilderMode = false;
playerMovement.movementSpeed_magnitude = playerMovement.walkSpeed;
comboSlotValue = 0;
for (int i = 0; i < testComboInputArray.Length; i++)
{
testComboInputArray[i] = 0;
}
}
}
void printComboKeysValues()
{
if (onBuilderMode == true)
{
if (Input.GetKeyDown(metal))
{
comboSlotValue = q_metalCode;
}
if (Input.GetKeyDown(spark))
{
comboSlotValue = w_sparkCode;
}
if (Input.GetKeyDown(ammo))
{
comboSlotValue = e_ammoCode;
}
}
}
void CheckArrays()
{
if (testComboInputArray.SequenceEqual(testComboArray))
{
arraysAreEquals = true;
}
else { arraysAreEquals = false; }
}
void FillInputArray()
{
if (onBuilderMode == true)
{
int i = 0;
int range = testComboInputArray.Length;
////
if (i < range)
{
if (testComboInputArray[i] > 0)
{
i++;
}
if (i < range)
{
testComboInputArray[i] = comboSlotValue;
}
}
////
print("ArrayInout Length is " + range);
print("filling Array Slot " + i);
}
}
They way I'm trying to solve it is by creating two arrays:
public int[] testComboArray = { 1, 2, 3 }; this is the array that has already a sequence.
public int[] testComboInputArray = new int[3]; and this is the empty array that the player is supposed to fill.
What I did was asign int values to the QWE keys in the printComboKeysValues() basically if you press the Q key the variable comboSlotValue changes to 1, If you hit W it becomes 2 and E is 3.
The real problem starts in the FillInputArray() method basically what I'm trying to do is the player assings the first array slot (testComboInputArray[0]) to the comboSlotValue variable (which can be 1,2 or 3) after the slot is filled then I check if the value of the slot is greater than zero, meaning is no "empty" anymore then increase i by 1 to move into the [1] slot and finally [2] but it never makes it past [1]. the i++ stops adding and never reaches [2]
the two solutions I tried were:
void FillInputArray()
{
if (onBuilderMode == true)
{
int i = 0;
int range = testComboInputArray.Length;
////
while (i < range)
{
testComboInputArray[i] = comboSlotValue;
if(testComboInputArray[i] > 0)
{
i++;
}
}
////
print("ArrayInout Length is " + range);
print("filling Array Slot " + i);
}
}
this one "crashes" Unity because it creates an infinite loop.
and:
void FillInputArray()
{
if (onBuilderMode == true)
{
int i = 0;
int range = testComboInputArray.Length;
////
if (i < range) //check if i is smaller than the array range
{
int currentSlot = testComboInputArray[i];//get slot to modify
currentSlot = comboSlotValue; //the current slot will be added the value of the player input
if (currentSlot > 0) // if the current slot is not zero then move to next slot
{
i++;
}
}
////
print("ArrayInout Length is " + range);
print("filling Array Slot " + i);
}
}
this one never adds up i, any ideas of to what Im doing wrong or not doing?
Answer by fafase · Mar 25, 2019 at 07:23 AM
For the sake of helping, here is a small code that takes an input to be checked against an expected input:
public class Test : MonoBehaviour {
List<string> list = new List<string>();
List<string> readAgainst = new List<string>() { "a", "b", "c", "d" };
private float timer = 0;
void Update ()
{
timer += Time.deltaTime;
if (Input.anyKeyDown)
{
timer = 0f;
string str = Input.inputString;
list.Add(str);
CheckContent();
}
if(timer > 1f)
{
list.Clear();
}
}
void CheckContent()
{
if(list.Count < readAgainst.Count) { return; }
if(list.Count > readAgainst.Count) { list.RemoveAt(0); }
for(int i = 0; i < list.Count; i++)
{
if(list[i].Equals(readAgainst[i]) == false) { return; }
}
Debug.Log("Build");
}
}
it has first a list in which you will store the input. The second list is the expected input (abcd). There is also a timer so the each new key has 1s to be entered or it clears the list. This avoids unexpected action such as typing xzab and then later cdef and seeing a build you would not expect.
It checks if any key is down, then resets the timer to 0 and adds that key to the list.
Moves on to check if the current state of the list is matching the readAgainst list (our expected input).
If the two lists are not same length, stop here. if the list is larger that our readAgainst then remove the first one. This is not perfect, you should still check more for length but considering you would not enter two keys at once, it will be fine for now.
If the two list are same count, then we move on to compare, if any key different, we return from method.
If the loop goes all the way, it means we have the same two collections.
Answer by jdean300 · Jan 15, 2018 at 04:38 AM
If I understand what you are trying to do with that function, this should do the trick. Each call puts the value of comboSlotValue
into the next available spot of testComboInputArray
void FillInputArray()
{
if (!onBuildMode) return;
for (int i = 0; i < testComboInputArray.Length; i++)
{
// If this slot hasn't been set...
if (testComboInputArray[i] != 0)
{
// Set it
testComboInputArray[i] = comboSlotValue;
// We are done with this input. Next call will fill the next slot.
return;
}
}
Debug.logError("The combo input array was already filled");
}
Thanks for the asnwer, unfortunately it did not solve my issue, as soon as I run the code the Debug.LogError
message displays saying that the array was already filled.
to clarify more, when onBuilder$$anonymous$$ode == true
that's when you can set the comboSlot
variable from 1 to 3, then when left mouse is pressed it calls void CheckArrays()
which will tell if the arrays are equals or not.
This would just fill the array with the first input on 3 frames (unless you manage to hit 3 keys on miliseconds) to fix it you need to reset the comboSlotValue each time the value had been registered (so it is Input based) something like this
void FillInputArray()
{
if (!onBuild$$anonymous$$ode && comboSlotValue !=0) return;
for (int i = 0; i < testComboInputArray.Length; i++)
{
// If this slot hasn't been set...
if (testComboInputArray[i] != 0)
{
// Set it
testComboInputArray[i] = comboSlotValue;
// We are done with this input. Next call will fill the next slot.
comboSlotValue = 0; //resets it
return;
}
}
//DoSomething()
}
Also Throwing an error just because the array is full is plainly wrong whenever the execution reaches that point you should check if combo is valid and perform the effect of given combo or in case it is not valid reset the array so you may repopulate it.
Appart from that i would just apply the values directly on printCombo$$anonymous$$eysValues() (terrible name) with the help of member variable to hold the current Index, you are overcomplicating the whole thing for no reason.
Cheers!
Thanks for the Answer, and yes I know my variable/method names are terrible, trying to fix that bad habit.
Anyway tried your implementation and it didn't work, the counter (i) never added up only filled the [0] slot. I think at this point I gonna try a different script altogether, I think the problem is more the script idea and not so much it's logic.
Thanks to the repliers for the help tough, good luck on your projects.
Answer by sniper02311 · Mar 25, 2019 at 04:14 AM
To get rid of the array is full error, shouldn't the loop check that the slot is NOT full or == 0? i.e. if (testComboInputArray[i] == 0
I could be wrong but sounds right to me. Otherwise you are saying if the array slot is not zero, then do something. Well, it is 0 at first. So, you should say, if array slot is empty (0), then do this.
Your answer
Follow this Question
Related Questions
How to set parents of all objects in an array? 1 Answer
AudioClip Import Order Randomized? 4 Answers
accessing gameObject script from an array 3 Answers
Passing an array to a function by reference? 1 Answer
Help with for loop and arrays 3 Answers