#They all have their own scripts named

1 messages · Page 1 of 1 (latest)

timber lake
#

also, let's do a thread

#

When you say "named the same", do you mean each enemy object has the same component attached to it?

#

for example, this is a Debris component

#

I have many objects with this Debris component on it.

swift wasp
#

No

#

Vampire has a vampire.cs script

#

Camper has a camper.cs script

#

Ect

timber lake
#

I wouldn't thinking about the enemy having the "vampire.cs script" attached

#

The enemy has a Vampire component

#

which happens to be defined in a script file named vampire.cs

swift wasp
#

This is a tiny game there will only be this one enemy and its a vampire and then im moving on from this god forsaken game

timber lake
#

Okay, so there's only one kind of enemy

#

So, you want to be able to find the closest enemy -- a game object with a Vampire component attached -- and reduce its health

swift wasp
#

Its also not entirely an enemy hence y i didnt call it enemy

#

Well first actually its the camper who wants to find the closest sleeping bag

timber lake
#

Got it.

#

So, first, we want to find sleeping bags

#

you just want to get every single sleeping bag that exists, right?

swift wasp
#

Yes but the idea is i want a method thats modular so I can just call FindNearest(myreference, theirreference(object,class,script , whatever)

#

So i dont have to custom write all this crap each time i just want to find the nearest something

timber lake
#

"script" isn't a kind of thing that actually exists in your game

#

scripts are just files that contain C# code

#

they do not exist anywhere in your scene

timber lake
timber lake
#
FindObjectsOfType<SleepingBag>();

This will give you an array containing every SleepingBag component in the scene.

#

Components have a transform property, so you can find the Transform of the component (and thus its position).

#

Then you just need to pick the one that has the smallest distance to the point you asked about.

#

The method will look a bit like this

swift wasp
#

Now what if i want to find the nearest sleepingbag that has a field named "available" set to true

timber lake
#
public static T FindClosest<T>(Vector3 position) where T : Component {
  T[] options = Object.FindObjectsOfType<T>();
  return options[0];
}
#

This method just picks the first one it finds.

#

But it's halfway there.

swift wasp
#

Ooh ok

timber lake
#

The <T> means it's a generic method. It doesn't work with a specific type.

#

You tell it what type you want to use.

#

where T : Component forces the type to be a component

swift wasp
#

I understand generics ☺️

timber lake
#

Ah, good.

timber lake
#

a predicate is a method that returns true or false

#
public static T FindClosest<T>(Vector3 position, System.Func<T, bool> predicate) where T : Component {
  T[] options = Object.FindObjectsOfType<T>();

  foreach (var option in options) {
    if (predicate(option))
      return option;
  }

  return null;
}
#

System.Func<T, bool> is a function that takes a T and returns a bool

#

So, you could use it like this

#

FindClosest(transform.position, x => x.available)

#

While you're at it, you could replace the first argument with a function that returns a score. You'd just pick the result with the highest score.

Mixing in LINQ, you could do...

public static T FindBest<T>(System.Func<T, float> scorer, System.Func<T, bool> predicate) where T : Component {
  T[] options = Object.FindObjectsOfType<T>();

  return options.Where(predicate).OrderByDescending(scorer).FirstOrDefault();
}
#

You would use it like this

#
FindBest<SleepingBag>(bed => -Vector3.Distance(transform.position, bed.transform.position), bed => bed.available);
#

the first function returns the negative distance between you and the bed

#

so further beds get a more negative score

#

(feel free to ask about any part of this if it's unfamiliar)

timber lake
swift wasp
#

Just when i think im getting the hang of c# 😂 then someone blows my mind again

#

Well atleast i found my next bit of stuff to study

timber lake
#

Functions that take other functions as arguments are great

#

You can wind up solving a lot of problems at once

swift wasp
#

Lambdas still take a while for my brain to parse i need to practise them more

timber lake
#

sure thing :p it's a lot

swift wasp
#

When i see a lamba i still get an error 404 😂

timber lake
#

You can use named functions if you want

swift wasp
#

So my whole plan is this:

timber lake
#
public void Gimme() {
  FindClosest<SleepingBag>(BagCloseness, BagUsable);
}

float BagCloseness(SleepingBag bag) {
  return -Vector3.Distance(bag.transform.position, transform.position);
}

bool BagUsable(SleepingBag bag) {
  return bag.available;
}
swift wasp
#

public Dictionary<Az.State, dynamic> targetStateConditions = new Dictionary<Az.State, dynamic>()

#

But then also on the recieving end

#

The same but states

timber lake
#

I've never used dynamic as a type parameter. scary.

swift wasp
#

So then when i look for the nearest objevt i look at the objects state dictionary

#

And see if my conditions ive added to my targetStateConditions

#

Are matched

#

This way i can simply set the target objectType and add or remove my conditions and find the nearest object related

#

To that

#

It allows me to dynamically check for variables in another object.

#

In a way i wouldnt be able to do if they were hardcoded fields

#

Thus the end goal is just to have a method i store in my shortcuts/dll class called FindNearest(targetObjectType, maxDistance, conditionsDictionary);

timber lake
#

If you want to pass the type as an argument (e.g. typeof(SleepingBag)), you'll need to do reflection to read fields from the SleepingBag you find

#

because you won't know the type at compile time

#

IIRC, GameMaker's scripting language doesn't have static types

#

I would be careful about trying to force that same programming style into Unity and C#.

swift wasp
#

This might seem like overkill for this game but im actually setting it up for the real game im makig after this, the current game is just to set everything i need up and learn how the basics work

#

Oh nah the object type im refering to is already solved by what you showed me

#

FindObjectsOfType<>

#

Then i just use an enum setup in my shortcuts class to find the matching "field" in the targets dictionary

#

And check it against my conditions

#

===

#

I am reading through everything you wrote

#

To try and figure it out, thank you so much

#

For this answer

swift wasp
#

In the same way you are accesing the transform

timber lake
#

Both of those methods accept a SleepingBag argument.

#

They aren't taking an object or Component or MonoBehaviour or something else that's vague

#

I can use them with FindClosest because they match the type parameter.

#

FindClosest itself has no clue that SleepingBag exists.

#

Perhaps you're asking about access modifiers, though

swift wasp
#

So SleepingBag isnt of GameObject type?

timber lake
#

Correct.

swift wasp
#

Then what is its type

timber lake
#

That's the type!

#

SleepingBag

#

SleepingBag isn't a variable. It's a type.

swift wasp
#

So through SleepingBag i have access to all its fields of all its scripts?

timber lake
#

not "all of its scripts"

#

SleepingBag is a type. It's probably a class you defined

#

If you have an object of type SleepingBag, you can access any public members of SleepingBag

swift wasp
#

Ooh

timber lake
#

public fields, methods, properties, types, ...

#

C# has no clue what's going on in your Unity scene.

swift wasp
#

Ok so i started off with this solution but it didnt work:

timber lake
#

that's an important thing to understand

#

it doesn't matter if there's an object named SleepingBag, or if there's a SleepingBag attached to a game object, or if SleepingBag components are always attached to the same object as a Pillow component

#

the C# compiler has no clue about any of that

swift wasp
#

I cant find it now but the one solution i found online told me to create a object pool static HashSet then iterate through the HashSet to get the closest one but then I decided to put that in a Interface and let everyone just inherent from the interface to have that same pool and inheret that same function so i wouldnt have to add it to each object individually

#

They would be added to the pool in the OnEnable() method

#

But then the onEnable method didnt seem to run so i had to move it to Start()

#

Then i thought hey to hell with the whole interface let me just make a GameObject pool in my shortcuts class and pool all the objects in there

#

But then i didnt know how to access their fields

#

Which is how i ended up here

swift wasp
timber lake
#

When you declare a class, you're declaring a new type

swift wasp
#

Yeah

#

I just wanted to know if thats what u meant by type

#

So ur saying i should be iterating through instances of the class essentially

#

Which is what i did and I also did it with an Interface to group all the seperate objects classes together

timber lake
#

You can use abstract classes and interfaces to create a hierarchy of types

swift wasp
#

The issue is i did all that but for some reason the OnEnable method in the Interface didnt add said class inherenting from the interface to the pool

#

If that worked everything else would have worked, finding the nearest, checkimg for certain fields to be certain values all of it