Using FindObjectofType and FindObjectOfTypeAll Unity methods - unity3d

GameObject[] rm = FindObjectsOfTypeAll(typeof(RoadMovement)) as GameObject[];
if (Input.GetKeyDown (KeyCode.LeftArrow))
{
foreach(GameObject r in rm) //objectRefrence not set to instance of an object error here
{
var bounds1 = r.renderer.bounds;
var bounds2 = player.renderer.bounds;
Transform roadtransform = r.transform;
if(bounds1.Intersects(bounds2))
{
if (this.transform.position.x > r.renderer.bounds.min.x)
this.transform.position = new Vector3 (this.transform.position.x - 0.6f, this.transform.position.y, this.transform.position.z);
}
}
}
What is difference between FindObjectOfType and FindObjectOfTypeAll? I want to get all the objects that have RoadMovement script attached to them.I understand the error: Object reference not set to an instance but not sure how to fix this?

First problem: FindObjectsOfTypeAll has been deprecated for quite some time, and is no longer documented at all in current versions of Unity. Because you're comparing objects in the scene, it looks like you want Object.FindObjectsOfType.
Second problem: the lookup call you're making doesn't return an array of GameObjects, so the as operator will return null when the cast fails. You mentioned that RoadMovement is a behavior script you wrote. That implies that every RoadMovement has a GameObject, but not that every RoadMovement is a GameObject.
This is also why you're getting an InvalidCastException that you're asking about. Understand your return types and you will understand the error.
Recent Unity versions even added a generic version of FindObjectsOfType:
RoadMovement[] roadMovements = Object.FindObjectsOfType<RoadMovement>();
foreach (RoadMovement roadMovement in roadMovements) {
GameObject myGameObject = roadMovement.gameObject;
//do something
}

Related

Why when materials gets instanced, using renderer.sharedMaterial is the new instance but not the file?

I have a list of materials set by hand called LookUpMaterials and an object which I want to compare if it has those materials.
If both materials correlate, add them to a new list "ChangeableMaterials".
I'm comparing using the sharedMaterials so everything is fine at first. But, when adding the .material to this new list, it creates a instance of the material.
Note: Creating the instance using .material is intended since I'm gonna edit this material anyway.
List<Material> ChangeableMaterials = new List<Material>();
Renderer[] renderers = GetComponentsInChildren<Renderer>();
for(int i = 0; i < renderers.Length; i++)
{
for(int j = 0; j < renderers[i].sharedMaterials.Length; j++)
{
if(LookUpMaterials.Contains(renderers[i].sharedMaterials[j]))
{
ChangeableMaterials.Add(renderers[i].materials[j];
}
}
}
In the first comparison (i,j == 0,0), it runs ok and the material is added to the list. All materials turns into Instances. But then when using sharedMaterials also spits out materials (Instances) in place of the original files and the comparison fails.
I've read multiple times that .sharedMaterials should be the file and not the instance, this is not being the case!
Can someone help me? I can't find the mistake here, just plain confused..
Here's 3 lists how Debug.Log() spits the name of the material
LookUpMaterials
011_Pillow
.materials
011_Pillow (Instance)
.sharedMaterials
011_Pillow (Instance) - Shouldnt be only 011_Pillow?

"IllegalArgumentException: Argument is not an array" error in processing when using append();

My code is as so...
ArrayList<Ray> rays = new ArrayList<Ray>();
Particle() {
for(int a=0; a < 360; a+=10) {
append(rays, new Ray(position, radians(a)));
}
}
I'm initializing an ArrayList of the class Ray. Then I run through a for loop and am attempting to
append a new Ray() to the list. I get no errors in the editor but whenever I run the code I get the error message: IllegalArgumentException: Argument is not an array
I've looked around and nothing seems to answer my question. Why is this happening?
The append function is for use with arrays (e.g.: rays[]). However rays is an ArrayList. Hence, you need to use the add method:
append(rays, new Ray(position, radians(a)));
rays.add(new Ray(position, radians(a));

std::lock_guard (mutex) produces deadlock

First: Thanks for reading this question and tryin' to help me out. I'm new to the whole threading topic and I'm facing a serious mutex deadlock bug right now.
Short introduction:
I wrote a game engine a few months ago, which works perfectly and is being used in games already. This engine is based on SDL2. I wanted to improve my code by making it thread safe, which would be very useful to increase performance or to play around with some other theoretical concepts.
The problem:
The game uses internal game stages to display different states of a game, like displaying the menu, or displaying other parts of the game. When entering the "Asteroid Game"-stage I recieve an exception, which is thrown by the std::lock_guard constructor call.
The problem in detail:
When entering the "Asteroid Game"-stage a modelGetDirection() function is being called to recieve a direction vector of a model. This function uses a lock_guard to make this function being thread safe. When debugging this code section this is where the exception is thrown. The program would enter this lock_guard constructor and would throw an exception. The odd thing is, that this function is NEVER being called before. This is the first time this function is being called and every test run would crash right here!
this is where the debugger would stop in threadx:
inline int _Mtx_lockX(_Mtx_t _Mtx)
{ // throw exception on failure
return (_Check_C_return(_Mtx_lock(_Mtx)));
}
And here are the actual code snippets which I think are important:
mutex struct:
struct LEMutexModel
{
// of course there are more mutexes inside here
mutex modelGetDirection;
};
engine class:
typedef class LEMoon
{
private:
LEMutexModel mtxModel;
// other mutexes, attributes, methods and so on
public:
glm::vec2 modelGetDirection(uint32_t, uint32_t);
// other methods
} *LEMoonInstance;
modelGetDirection() (engine)function definition:
glm::vec2 LEMoon::modelGetDirection(uint32_t id, uint32_t idDirection)
{
lock_guard<mutex> lockA(this->mtxModel.modelGetDirection);
glm::vec2 direction = {0.0f, 0.0f};
LEModel * pElem = this->modelGet(id);
if(pElem == nullptr)
{pElem = this->modelGetFromBuffer(id);}
if(pElem != nullptr)
{direction = pElem->pModel->mdlGetDirection(idDirection);}
else
{
#ifdef LE_DEBUG
char * pErrorString = new char[256 + 1];
sprintf(pErrorString, "LEMoon::modelGetDirection(%u)\n\n", id);
this->printErrorDialog(LE_MDL_NOEXIST, pErrorString);
delete [] pErrorString;
#endif
}
return direction;
}
this is the game function that uses the modelGetDirection method! This function would control a space ship:
void Game::level1ControlShip(void * pointer, bool controlAble)
{
Parameter param = (Parameter) pointer;
static glm::vec2 currentSpeedLeft = {0.0f, 0.0f};
glm::vec2 speedLeft = param->engine->modelGetDirection(MODEL_VERA, LEFT);
static const double INCREASE_SPEED_LEFT = (1.0f / VERA_INCREASE_LEFT) * speedLeft.x * (-1.0f);
// ... more code, I think that's not important
}
So as mentioned before: When entering the level1ControlShip() function, the programm will enter the modelGetDirection() function. When entering the modelGetDirection() function an exception will be thrown when tryin' to call:
lock_guard<mutex> lockA(this->mtxModel.modelGetDirection);
And as mentioned, this is the first call of this function in the whole application run!
So why is that? I appreciate any help here! The whole engine (not the game) is an open source project and can be found on gitHub in case I forgot some important code snippets (sorry! in that case):
GitHub: Lynar Moon Engine
Thanks for your help!
Greetings,
Patrick

TActorIterator<T> to T

Im having problems with something,
Im not sure if its my understanding of pointers, or Unreal itself. Here is my code
TArray<Anode> nodes;
TActorIterator<Anode> ActorItr = TActorIterator< Anode >(GetWorld());
while (ActorItr) //Go through EVERY Node and check distance
{
if (this->GetUniqueID() != ActorItr->GetUniqueID())
{
//Check Distance
if (FVector::DistSquared(this->GetActorLocation(), ActorItr->GetActorLocation()) < 262144) //Check the distance between the two nodes.
{
Anode node = ActorItr;
//Anode* node = Cast<Anode>(*ActorItr);
nodes.Add(node); //Calls a error because
//cannot convert from 'TActorIterator<Anode>' to 'Anode'
}
}
}
}
So my issue is i cannot convert the Actor Iterator to my TArray, and i have played around with de-referencing etc, i got it to compile but crash at run-time. Thanks!
Edit: For clarity
i have tried
Anode node = *ActorItr;
but got a error C2440: 'initializing' : cannot convert from 'Anode *' to 'Anode'.
I then tried
Anode *node = *ActorItr;
nodes.Add(*node);
It compiled but created a run time error with unhanded memory or something, i think this is because its just handing the pointer to the TArray without handling the issue (is that right?). I understand the concept i feel, but not the syntax.
The actor iterator is not an actor, so direct assignment doesn't make any sense. Try dereferencing the iterator (Anode* node = *ActorItr;), that operator should be overloaded to return the current element of the iteration, i.e. the node you want to use.

saving player information in an external file

This is the main menu in my first test 2d game in the world of unity :
I want to save high scores and if the player pressed the "Best Scores" button I want to show them the best scores yet ^^ , so I think I need to use an external file to save this type of information and open it at run time ... How ? which kind of files is the best to perform that ?
In addition to the answer above:
PlayerPrefs doesn't handle and store custom types and collections unless you cast those types to strings or other data, though. It's really useful to convert desired data to JSON and store the JSON string in PlayerPrefs, then fetch and parse that data when you need it again. Doing this will add another layer of complexity, but will also add another layer of protection and the ability to encrypt the data itself. Also, the Web Player is currently the only platform that has limits on PlayerPrefs according to Unity's docs:
There is one preference file per Web player URL and the file size is
limited to 1 megabyte. If this limit is exceeded, SetInt, SetFloat and
SetString will not store the value and throw a PlayerPrefsException.
Source:
http://docs.unity3d.com/Documentation/ScriptReference/PlayerPrefs.html
Writing:
PlayerPrefs.SetInt("score",5);
PlayerPrefs.SetFloat("volume",0.6f);
PlayerPrefs.SetString("username","John Doe");
// Saving a boolean value
bool val = true;
PlayerPrefs.SetInt("PropName", val ? 1 : 0);
PlayerPrefs.Save();
Reading:
int score = PlayerPrefs.GetInt("score");
float volume = PlayerPrefs.GetFloat("volume");
string player = PlayerPrefs.GetString("username");
bool val = PlayerPrefs.GetInt("PropName") == 1 ? true : false;
The simplest solution is using PlayerPrefs. It has limited space and a small set of data that can be saved (int, float, string), but it could be enough for a simple game.
If you need more space or more complex data structures to be saved, than you have to store them on the file system itself (or in a server if you have some backend support). Unity doesn't provide any built-in support for this.
C# is like this
//these variables will send the values in.
public static string exampleString = "hi youtube"; //it needs to be public ans static
public static int exampleInt = 1;
public static float exampleFloat = 3.14;
//these vaibles will collect the saved values
string collectString;
int collectInt;
float collectFloat;
public static void Save () { //this is the save function
PlayerPrefs.SetString ("exampleStringSave", exampleString);
// the part in quotations is what the "bucket" is that holds your variables value
// the second one in quotations is the value you want saved, you can also put a variable there instead
PlayerPrefs.SetInt ("exampleIntSave", exampleInt);
PlayerPrefs.SetFloat ("exampleFloatSave", exampleFloat);
PlayerPrefs.Save ();
}
void CollectSavedValues () {
collectString = PlayerPrefs.GetString ("exampleStringSave");
collectInt = PlayerPrefs.GetInt ("exampleIntSave");
collectFloat = PlayerPrefs.GetFloat ("exampleFloatSave");
)
void Awake () { //this is simialar to the start function
Save ();
CollectSavedValues ();
}
void Update () {
Debug.Log (collectString);
Debug.Log (collectInt);
Debug.Log (collectFloat);
}