#archived-code-advanced

1 messages · Page 186 of 1

waxen roost
mint sleet
#

Hello people. What should I do for exception handing in my API?

#

When I encounter an error (for example in the validation) should I throw an exception or return an error object to the user having the details of the error with the boolean 0

livid kraken
#

You should throw a exception

#

With descriptive text

stuck onyx
#

Is it possible to detect when your camera is NOT rendering anything? just the skyview?

#

i would like to detect when the player has moded the camera away from the map

#

to bring him back

#

but how can I know this?

novel plinth
#

ideally you'd need to implement some sort of a Dead zones in your game

#

so certain areas can only accessible to certain objects in your game

placid robin
#

Does anyone happen to know with which version Unity went from caching builds in Temp to Library?

uneven fossil
#

Hello. I am trying to make a serializable class in Unity to read from a JSON. However, it's a class whose members will be arbitrary. In essence, I want to be able to read from a JSON into a <string, object> Dictionary.

#

I am having some trouble using the JsonUtility.fromJSON method, which seems to not like my serializable class, as it never calls the constructor that takes the SerializationInfo.

#

I do not wish to import a package such as Newtonson's JSON.Net package, because I only need this one functionality...

#

Any recommendations?

#

It never enters here.

#

if I add a default constructor, it calls that one.

#

Which is what I assume is happening.

flint sage
#

Unity's serializer doesn't support that

#

You should use json.net or something similar

#

There's also some other small json libraries that might do what you want like minijson

stuck onyx
#

@novel plinth im afraid for this case would be hard because the cam tilt rotation... take a look:

#

this one is sttill valid

#

this one it sttill shouild be valid since player still sees a little part of the map

novel plinth
#

you can just restrict the movement of the camera then

stuck onyx
#

this is the onne that should trigger the actio

#

yeah, restricting the movement leads to otther problems buttthanks

#

i guess there is no way to know when the cam is not rerndering any object right?

#

maybe raycasting

#

making a boxraycast

novel plinth
stuck onyx
#

yeah the render is visible im tryingn witth butt is not 100% accurae

#

accuratet

novel plinth
#

the latter is a bit too much for your simple use case tbh

stuck onyx
#

ttheres a botttom object in the map

novel plinth
stuck onyx
#

and i assigened a script with the OnBecameVisible

#

and OnBecameInvisible

#

but sometimes i dont see the map and itt doesnt trigger, i think is not accurate

#

I guess the render isvisible, is ddirectly connected to OnBecameVisible

#

ill try

novel plinth
uneven fossil
stuck onyx
#

what kind of camera

#

this is a perspective camera with autotilt and i think sometimes is not 100% accurate whatt the script says itts on cam andwhat it is

#

Ill try with the simulator instetad of editor just in case

surreal vessel
#

yeah but imo scriptable objects really would suck for this, imagine having a folder full of objects with numbers

regal olive
#

i have an editor script to control whether a variable appears or not on the editor depending on the type of my item. But this line is breaking my code? Does anyone know how i should proceed to do this with a variable of type Color?

#

all the others are ints floats or bools, i guess that's the problem

flint sage
#

wdym, colors work fine in PropertyFields?

regal olive
#

well when I add that specific line this happens

#

i get an error and a ton of my properties disappear from the editor script

flint sage
#

What's the stack trace of that error

#

That sounds more like hiddenResourceColor doesn't exist

regal olive
#

sends me to that line

#

lemme double check

flint sage
#

Send the stacktrace here

regal olive
#

it should exist, am i missing something?

flint sage
#
    private static bool IsChildrenIncluded(SerializedProperty prop)
    {
      switch (prop.propertyType)
      {
        case SerializedPropertyType.Generic:
        case SerializedPropertyType.Vector4:
          return true;
        default:
          return false;
      }
    }```

Is the source of the method throwing the NRE
#

So it can't find that field somehow

#

You sure that's a Unity Color?

regal olive
#

hmmm okay maybe that's the problem

#

got a lot of colors on my project

#

do i need any include?

flint sage
#

Wat?

#

Is that variable UnityEngine.Color or some other Color type?

regal olive
#

might be a color from another namespace or class i'm guessing

flint sage
#

Right, so double check that and make sure it's Unity's COlor

regal olive
#

is there another way i don't have to do this?

#

just writing color seems to no work it doesn't let mne select the proper Color type

flint sage
#

Don't import the other Color into that class

stuck onyx
#

Could someonne help me how to make some sort of raycast, boxcast, or planecast with the camera borders there ?

snow grotto
#

@stuck onyx You can translate camera space to world space and align a box cast but it really depents on what you want to achieve

sly grove
stuck onyx
#
var raytopRight = Cam.ScreenPointToRay(new Vector3(Screen.width, Screen.height, 0));
            Physics.Raycast(raytopRight, out topRightHit, 1000,````
stuck onyx
#

to rotate the camera 180 degrees

cerulean wasp
#

What would be a good way to add grass to procedurally generated mesh terrain?

latent vine
#

Guys

#

anyone can help me out

#

        internal static void SaveCubemapToFile(Cubemap cubemap, string path)
        {

                CubemapFace[] faces = new CubemapFace[] {
                CubemapFace.PositiveX, CubemapFace.NegativeX,
                CubemapFace.PositiveY, CubemapFace.NegativeY,
                CubemapFace.PositiveZ, CubemapFace.NegativeZ };

            Texture2D Text = new Texture2D(cubemap.width, cubemap.height);

            foreach (CubemapFace face in faces)
            {
                try
                {
                    Log.Debug($"Generating Texture of {face}");
                    Text.SetPixels(cubemap.GetPixels(face));
                    Log.Debug("Saving Texture...");
                    Text.SaveTextureAsPNG(path, face.ToString() + ".png");
                    Log.Debug($"Saved {cubemap.name} {face.ToString()}");
                }
                catch (Exception e)
                {
                    Log.Exception(e);
                }
            }
        }
#

tryin to copy the cubemaps

#

and save them

#
                    Graphics.CopyTexture(Text, 0, 0, cubemap, (int)face, 0);

#

i tried with this, all i get is a blank grey png file

#

this is what it comes out in all cubemaps faces

austere jewel
#

Try calling Apply on the texture after setting pixels

latent vine
#

shouldn't Graphics do it?

austere jewel
#

why would it?

latent vine
#

givin a try again

#

i thought so?

#

nope, again

#
**        internal static void SaveCubemapToFile(Cubemap cubemap, string path)
        {

                CubemapFace[] faces = new CubemapFace[] {
                CubemapFace.PositiveX, CubemapFace.NegativeX,
                CubemapFace.PositiveY, CubemapFace.NegativeY,
                CubemapFace.PositiveZ, CubemapFace.NegativeZ };

            foreach (CubemapFace face in faces)
            {
                try
                {
                    Texture2D Text = new Texture2D(cubemap.width, cubemap.height);
                    Log.Debug($"Generating Texture of {face}");
                    Graphics.CopyTexture(Text, 0, 0, cubemap, (int)face, 0);
                    Text.Apply();
                    Log.Debug("Saving Texture...");
                    Text.SaveTextureAsPNG(path, face.ToString());
                    Log.Debug($"Saved {cubemap.name} {face.ToString()}");
                }
                catch (Exception e)
                {
                    Log.Exception(e);
                }
            }
        }
tranquil copper
#

For context: I am trying to create a simple mechanic, which is regeneration for the player. However, I wanted it to change depending on the environment the player is in, so I was thinking of having the rate in which the regeneration happens change depending on how green the environment is. To do that, I was thinking of taking the camera's display and checking the average RGB value from that, and see how closely it would resemble pure green.

Then I encountered the problem of how I would do so. So, I am currently asking how I would program that in.

I don't know if it would fit in this channel, but the question wasn't being answered in either beginner nor general code, so I decided to post it here. I've been searching everywhere to figure it out, but I simply couldn't find a good answer.
Thank you for reading, and maybe even answering.

austere jewel
latent vine
#

the cubemap texture IsReadable is not set to true

#

im trying to figure a workaround to sort of "futureproof" it and ignore the isReadable flag

austere jewel
#

Maybe you ought to flip the arguments in the CopyTexture call around

#

because you're copying the texture into the cubemap face right now, which doesn't seem right

latent vine
#

im trying to save the cubemap faces back to .png

#

not copy the texture into the cubemap

austere jewel
latent vine
#

how so?

#

show me

austere jewel
#

Graphics.CopyTexture(Text, 0, 0, cubemap, (int)face, 0);

#

src : Source texture. : Text

#

dst: Destination texture. : cubemap

latent vine
#

oh

#

givin a try again

#

nope, just flipped em and still same results

#
        internal static void SaveCubemapToFile(Cubemap cubemap, string path)
        {

                CubemapFace[] faces = new CubemapFace[] {
                CubemapFace.PositiveX, CubemapFace.NegativeX,
                CubemapFace.PositiveY, CubemapFace.NegativeY,
                CubemapFace.PositiveZ, CubemapFace.NegativeZ };

            foreach (CubemapFace face in faces)
            {
                try
                {
                    Texture2D Text = new Texture2D(cubemap.width, cubemap.height);
                    Log.Debug($"Generating Texture of {face}");
                    Graphics.CopyTexture(cubemap, 0, 0, Text, (int)face, 0);
                    Text.Apply();
                    Log.Debug("Saving Texture...");
                    Text.SaveTextureAsPNG(path, face.ToString());
                    Log.Debug($"Saved {cubemap.name} {face.ToString()}");
                }
                catch (Exception e)
                {
                    Log.Exception(e);
                }
            }
        }
#

@austere jewel

austere jewel
#

You have (int)face in the wrong place.
Also, now you're no longer doing SetPixels, calling Apply is wrong and will just yield undefined results

#

because the CopyTexture only occurs on the GPU, so Apply is just overwriting it

#

I don't know how SaveTextureAsPNG works though so I can't say whether it'd do what you want it to

latent vine
#

save texture just processes it back to png if not readable

#

where i should put (int) face?

austere jewel
#

Graphics.CopyTexture(cubemap, (int)face, 0, Text, 0, 0); associated with the element of the cubemap

snow grotto
#

What would be the best way to approach IK in 2022, should I use the new rigging system or the old animation IK pass?

undone coral
undone coral
undone coral
#

gray is unusual

#

why would it be gray, and not all black, if it were an empty texture?

austere jewel
#

Grey is one of the common outputs to undefined textures

latent vine
runic canopy
#

Guys Im having an issue, Im working with toggles I instantiate a bunch of toggles that are ment to be clicked when a user wants that question to be added. After I change scene and create the question doc, if the user chooses to go back and sellect different questions this error pops up
(MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.)

#

Google says something about singletons but Im not sure where that would help

granite viper
#

you're trying to access an object you've destroyed

#

when you switch scenes everything in that scene gets destroyed

#

so for some reason you're still referencing something from the old scene

runic canopy
#

Yeah I understand that, but Im essntially re-instantiating the objects right ? When I go back at the scene

#

Im calling a static method that I used in the first place to instantiate those objects

granite viper
#

they're different objects

#

if you go back to the scene

runic canopy
#

Yeah but still I assign them in the start function when I switch scenes

#

How should I fix this cause Ive been struggling to be honest :/

granite viper
#

let me see the code

runic canopy
#

Its quite a lot are your sure ?

#

and dirty

#

but I could use some advice

granite viper
#

just the relevant portions

runic canopy
granite viper
#

use triple backticks to make a code block -> ```

runic canopy
#

Im trying to paste the code

#

oh

#
//
public void FromMenuToSellectionView(int SceneID) 
    {
        LocateCategory(); // this just gets and filters the input from a field
        SceneManager.LoadScene(SceneID); 
    }
public void nextPage(int SceneID)// this is what I use to go to the final scene
    {
        
        int numOfQuestions = questionsFormat.Count;
        using (var connection = new SqliteConnection(dbName))
        {
            connection.Open();
            using (var command = connection.CreateCommand())
            {
                command.CommandText = "DELETE FROM SellectedQuestions";
                command.ExecuteNonQuery();
                for (int i = 0; i < numOfQuestions; i++)
                {
                    if (checkToogles[i].GetComponent<Toggle>().isOn)
                    {
                        command.CommandText =
                            "INSERT INTO SellectedQuestions(Τύπος,Αντικείμενο,Ερώτηση,ΕπιλογήΑ,ΕπιλογήΒ,ΕπιλογήΓ,ΕπιλογήΔ,Απάντηση) VALUES ('" +
                            questionsFormat[i].questionCategory + "','" + questionsFormat[i].type + "','" +
                            questionsFormat[i].question + "','" + questionsFormat[i].answer1 + "','" +
                            questionsFormat[i].answer2 + "','" + questionsFormat[i].answer3 + "','" +
                            questionsFormat[i].answer4 + "','" + questionsFormat[i].correctIndex + "');";
                        command.ExecuteNonQuery(); // It executes the command the number of questions maybe ? 
                    }
                }
                connection.Close();
            }
        }
        storeSellectedQuestions();
        SceneManager.LoadScene(SceneID);
    }

public void fromFinalToPreview(int SceneID) // this is what I use to to go back to the previous scene
    {
        if (!initialized)
        {
            initialized = true; 
            SceneManager.LoadScene(SceneID);
        }
    }```
#

And Im doing this ugly for loop to assign each toggle to each question

granite viper
#

which line is causing the nullref?

runic canopy
runic canopy
runic canopy
runic canopy
#

if (checkToogles[i].GetComponent<Toggle>().isOn) // this is in the sellection/Preview scene

#

I have a button assigned to nextPage(), and as soon as I click is that error pops up. saying checkToogles[i].GetComponent<Toggle>().isOn is destroyed

granite viper
#

are both of those scripts inside the Preview/Sellection scene?

#

are you changing scenes in between the second code block and the first getting called?

runic canopy
#

yes the for loop as well as the nextpage script are in the preview/sellection scene

#

the very last script esentially creates a pdf document with all sellected quetions in preview/sellection scene

#

I gave the option to the user to go back and choose different questions, with is the fromFinalToPreview method

granite viper
#

something is destroying your toggle buttons looks like

fiery nebula
#

Hey, i want my square to go from one yellow point to the next one by passing through red points. Currently i can go by a system of pathfinding from one point yellow to another. I would like to add some points between two yellow point

runic canopy
granite viper
#

presumably

#

I don't see anything that would cause the behaviour you're experiencing in the code you posted

#

are you destroying things elsewhere

runic canopy
#

well no :/

granite viper
#

do you have multiple scripts in the scene perhaps

runic canopy
#

wait

#

I think I do

runic canopy
granite viper
#

you're definitely doing something funky, but it's not obvious from what you've posted

runic canopy
#

I do create a list of objects which I dont clear after I move to the next scene

#

ohh, I think I got it.

runic canopy
#

Im pretty sure thats it

#

thanks a lot for hellping

granite viper
#

yw

cedar ledge
#

how can she slap???

granite viper
#

did you add the requirement after you added the script?

#

it's not retroactive

cedar ledge
#

oh darn

#

i feel like resetting should at least recheck it

granite viper
#

guess it doesn't

#

it's always been kind of a jank attribute anyway

cedar ledge
#

how so?

granite viper
#

for reasons like that

#

and I recall it created quite a headache for a friend's editor project because it's very magical and hard to script around

#

when you're dynamically creating objects

gray pulsar
cedar ledge
#

i didnt but i should have

#
IEnumerable<Vector3> goals;
IEnumerable<Vector3> Goals => goals ??= from GameObject go in GameObject.FindGameObjectsWithTag("NavPoint") select go.transform.position;

Is there a way to rewrite this as an autoproperty? I tried this, but here goals is read-only

IEnumerable goals => goals ??= from GameObject go in GameObject.FindGameObjectsWithTag("NavPoint") select go.transform.position;
#
IEnumerable<Vector3> goals { get; } = from GameObject go in GameObject.FindGameObjectsWithTag("NavPoint") select go.transform.position;

seems to be valid but I'm not sure if the FindGameObjectsWithTag() will work properly given the context.

#

yep lol

red osprey
#

So, if I await a Task.Run(), does Unity guarantee that the thread to complete the Task.Run() will be the game thread?

#

That seems to be the case.

cedar ledge
#

I'm not sure but look into UniTask if you haven't already

red osprey
#

I've heard of it. I would like to know what Unity guarantees.

#

(Thanks, though.)

cedar ledge
#

Are you asking because the following code needs to be run on the main thread?

#

If so, I think you can configure that using ConfigureAwait(true)

#

Otherwise, if the code inside of of the Run() needs to run on the game thread, then that's a job for a Coroutine

#

or a UniTask

quiet bolt
undone coral
granite viper
cedar ledge
# quiet bolt Never seen AutoGetComponent before :o

I can give you the code for it if you want. It works beautifully, and the field can even be readonly because it uses reflections. However, the performance of the code in the attribute could be improved, but I haven't looked into it.

undone coral
red osprey
#

I didn't say that I wanted to run tasks on the main thread.

undone coral
#

a task can run on multiple threads throughout its execution. they are separate things

quiet bolt
#

Tysm

undone coral
#

within an async method you can control which thread gets control when the task you're awaiting completes

#

it's very tricky

red osprey
#

I'm aware. I know how to manually use TaskCompletionSources in general. I'm asking what Unity does.

undone coral
#

you can use UniTask to easily express which Thread you want to "Return to"

#

unity out of the box is undefined behavior

#

so you have to use unitask to do this stuff

red osprey
#

Or I could just do the task completion sources myself, but it seems like Unity guarantees more than that. One second while I write up an example.

undone coral
#

you can reinvent unitask yes

#

reinventing unitask is a bad idea

#

one of the worst ideas out there

#

all the downsides of rediscovering unity idiosyncracies with none of the upsides of working code

red osprey
#
private Update()
{
  TestFunction();
}

private async void TestFunction()
{
  //I'm on game thread
  await Task.Run(() => {
    // I'm likely on a worker thread.
  });
  // In my testing, I am back on the game thread, likely because Unity specifies a SynchronizationContext, but that's not documented that I've found.
}
undone coral
#

yeah

#

you should definitely use unitask

#

it documents its answers to these questions

red osprey
#

Every time I add a dependency it causes crashes right before deadlines...

undone coral
#

i don't know either and i think the value of finding out, since it's not in the unity docs, is low - what they're saying is it might change

#

hmm

#

i don't think this is going to do that

red osprey
#

... If I can't trust Unity, then I'm just going to use blocking calls, because that's safer for the deadlines that I have.

#

But it looks like Unity resumes Task.Run()s on the game thread... that's been the case in my testing. Curious if that was just coincidence.

undone coral
#

@red osprey

private Update()
{
  // "Forget" is dealing with a critical gotcha. your IDE is warning
  // you about this
  TestFunction().Forget();
}

// void is another gotcha with async methods. ide is also warning
// you about this
private async UniTaskVoid TestFunction()
{
  await UniTask.SwitchToMainThread();
  //I'm on game thread
  await UniTask.SwitchToThreadPool();
  // now you're on the thread pool
  DoCostlyWork();
  await UniTask.SwitchToMainThread();
  // I'm on game thread
}
undone coral
red osprey
#

No thank you.

undone coral
#

i can see if you added dependencies in another life, like in javascript life

#

well, you don't pay for javascript libraries now do you? of course they're awful

#

unitask ships in all my games

#

anyway i'm trying to make it way easier for you to do what you need

#

that example is very cute and good

#

unitask forces you to deal with all the gotchas too.

#

in a good way

red osprey
#

I mean the easiest is if Unity already guarantees what my use case would be.

#

And one example is a voice chat library that I used that had two separate crashes, one on ARM64, and one on TCP.

undone coral
#

was it a FREE voice chat library?

red osprey
#

That forced me to ship my demo 32-bit only, which isn't allowed by Oculus.

#

Nope. Asset Store.

undone coral
#

did you write a ticket?

#

was it the $300 one?

#

or the $5 one

red osprey
#

I talked to the author. He didn't have a Quest.

undone coral
#

jk

#

it's okay dude

#

i don't want you to stress

#

i don't know if the body of Task.Run is on a worker thread

#

i know in unitask you can control it explicitly

red osprey
#

I'm asking as you LEAVE task.run

undone coral
#

the rest of the statement is correct

#

you will wind up on the unity main thread

red osprey
#

There we go. That was the question.

undone coral
#

however

#

with regular csharp tasks, you can put yourself in jeopardy easily

#

and that will not be the case

#

for example, if you are using RestEasy

cedar ledge
undone coral
#

you can easily wind up on the resteasy http client implementation's thread pool

#

or something weird like that

#

because resteasy is weird and radioactive

cedar ledge
#

If the worker can be whatever thread but the continuing context needs to be the game thread...

fresh salmon
#

Yeah ConfigureAwait will determine whether to resume the task on the thread that initially started it

cedar ledge
#

So he doesn't need a unitask here

fresh salmon
#

Nope

cedar ledge
#

You disagree?

undone coral
#

it's up to you. you can try to interact with all this radioactive stuff

#

that requires a degree in taskology

fresh salmon
undone coral
#

or you can use the thing that this cygames guy, maybe the greatest contributor to open source unity code, has made and ships in his huge games

cedar ledge
#

Lol just English things

fresh salmon
#

Yep

cedar ledge
#

The problem is that unitask isn't multiprogramming

undone coral
#

whereas in the past, when i use async or blocking code from libraries like grpc or resteasy, out of the box unity async can put me in surprising kinds of jeopardy due to all the gotchas of nude C# async

cedar ledge
#

My understanding is that unitask doesn't have the parallelism performance increase that tasks are great for

undone coral
#

i guess the most common place you'll run into "being int he wrong thread pool" is if you are configuring listeners, like for a websocket or tcp listening library

#

if you are using these things to await network messages, you might be better off using unirx

#

since nude C# async is challenging to use for channels / signaling this way

granite viper
#

nude async challenge

undone coral
#

i haven't even gotten into cancellation

#

if you don't Java you don't know why all this stuff exists

#

the .net docs certainly don't tell you

#

because those people don't even know

#

like, does X throw operation cancelled exception or not?

#

why does the token have iscancelled?

#

do i have to check this after every await? (basically, yes)

#

so many gotchas!

fresh salmon
#

Does it throw? You look at the docs or what intellisense tells you to check
The token has to track state whether the Cancel was called on the CTS so of course it has a flag, for methods to bail out if they don't throw an exception via ThrowIfCancellationRequested()

undone coral
fresh salmon
#

No

undone coral
#

hmm

fresh salmon
#

Talking about plain old C# TAP here, no Unity, no random assets

undone coral
#

the answers you gave to those questions sound arcane

#

arcane is a qualitative thing

#

it's arcane

fresh salmon
#

To you probably

undone coral
#

cancellation token linking, and whether or not you have to pass down a token, and how to do that, are also pretty arcane

#

i think it's arcane

fresh salmon
#

How would you do it then

undone coral
#

there is a ton of arcane stuff

#

well, it seems wrong to pass a cancellation token deep down into everything, and then having to declare every method (eventually) with CancellationTokenSource cancellationToken=default (or whatever)

fresh salmon
#

Let's say you implement a library that does async... stuff, and you want to implement something that would replace the TCS while still being compatible with the C# ecosystem

#

How would you do it

undone coral
#

i'm saying that because you start and stop the editor all the time, in practice you will need to cancel in the middle of unity async tasks all the time

#

so you have to deal with it up front, everywhere

#

and it's cantankerous and bad

#

and UniTask does some stuff to make life easier for you

fresh salmon
#

So yeah, you're just ignoring my question

undone coral
#

that's what i'm saying

#

that's how i would do "it"

#

meaning cancellation

fresh salmon
#

no no

undone coral
#

UniTask has WithCancellation extensions for common stuff, it has an OnDestroyToken, etc. etc.

#

it has good stuff for this

fresh salmon
#

No Unity, no external package

#

If you were in charge of developing the async cancellation system how would you do it

undone coral
#

i'm not sure. i don't write C# backend code. i don't use visual studio

#

i would probably do what Golang does, and back in java world, i would stick to what ron pressler did in quasar, which is now becoming java virtual threads i.e. fibers

#

in video games a lot more cancellation happens

#

than in stateless http backends. but anyway, who's writing those anymore

#

there isn't much value in the 10,000th stateless thing.

#

all the value of stateless crap has been mined, and only stateless stuff doesn't have to deal with cancellation

#

in java world, exhibit A is Vertx

#

you're talking about intellisense, and i use rider 🙂

#

video games are very stateful. i actualyl really liked experimenting with defining my whole game loop in one big async method

#

i think it's a viable way to make minigames / constrained experiences

#

you gain a lot from being forced to deal with something like cancellation, because it reflects real potential bugs

#

in my experience, backend C# code nowadays has a lot of clunky dependency injection. when people really just want a Kestrel and to add routes to it (i.e., they want Vertx in their C#)

#

in that context, yeah, i think the way C# does async makes sense. because it already coexists with this crummy, arcane thing that nobody wants

#

go doesn't have the concept of cancellation, but in its opinion it doesn't want you to model that using its stack at all

#

they don't do function coloring (i.e. marking a method as async), they don't have function polymorphism (i.e. throwing exceptions)

#

then again if i was more familiar with rust i'd probably say "whatever rust does" because they have spent the longest time thinking about this for all possible end user applications

#

rust has function coloring

tough tulip
# fresh salmon Talking about plain old C# TAP here, no Unity, no random assets

i kinda second this.
heavy reliance on some third party asset might work for indie projects, but you cannot always use a third party plugin everytime for every program you make in c#

i feel unirx is kind of bloated. also generally speaking (not just unirx) it becomes a very tedious process to migrate away your programming pattern from Unirx to vanilla c# style incase unirx gets abandoned

red osprey
#

C++20 coroutines are quite cute. (They don't have any consideration for threads... just the state machine to know where you're starting from each time you enter the "function".) So efficient that some people are actually using them to "await" RAM fetches. (Basically, write their code as if they're processing fetching processing fetching processing, etc.... but, in terms of what the CPU sees, it's everything up to and including the load, but before ever using any of the loads.)

urban warren
#

So I have been looking in to how to handle larger open worlds and it seems a common method is to split it up in to scenes which are additively loaded.

However unloading a scene will clear/reset any changes that were made in that scene. So if I understand correctly, when unloading a scene during play you need to save any changes the way you would when saving the whole game, and then load those changes when the scene is loaded.

Does that all sound correct, or am I missing something?

modest lintel
#

Sounds sound

compact ingot
#

there is no way in unity to prevent the engine from initializing all gameobjects in an additive load (even when its an async one) at least once

urban warren
#

Cool, glad I understand it correctly.

cedar ledge
#

How do I reinvent csharp so that I can create a new operator called "backwards equal" to allow for newValue = shouldUseFirstVariable ? defaultVariable : fallbackVariable which assigns the left side to the variable that the right side evaluates to

#

1 ≈ myInt;

urban warren
compact ingot
#

if you keep the scenes small enough it is manageable, or do it with very fine grained addressable loading

urban warren
compact ingot
urban warren
compact ingot
#

some also have a source license and modify the engine

#

do you have an example?

#

curious myself

urban warren
#

Subnautica is the first that comes to mind

modest lintel
#

how do you "hide" the loads?

red osprey
compact ingot
modest lintel
#

ah, portal types. Gotcha

urban warren
#

I also know Pine was made in Unity and Genshin Impact (but they for sure have a engine license)

compact ingot
#

overall unity and unreal are (have been) "terrible" engines for open world games

#

they can do it with workarounds but they have nothing in them that makes it easy

urban warren
compact ingot
#

open world = requiring lots of asset streaming

#

the other issue is scene management

red osprey
#

You'd need to profile that.

compact ingot
#

thats just atrocious

urban warren
#

Asset streaming, that is done with addressables right?

red osprey
#

Or just asset bundles in general.

compact ingot
#

either with addressables or scenes

urban warren
#

I need to look in to that more

compact ingot
#

raw bundles will melt your brain

stone swallow
#

hey guys, im trying to multiply a bunch of matrixes(4x4) tho the last row is always the same as the identity matrix. how can i multiply these faster by eliminating the need for accounting the last row?

cedar ledge
red osprey
#

It's a bit messy unless (like my current project) the use case is VERY simple.

#

"A bit".

#

In the cases that I've done additive loading/unloading, it's mostly just to transition between scenes while the user can do stuff in the load time.

urban warren
#

Alrighty, thanks all for the insight! Glad to know I am on the right track. I will carry on as is and I guess just figure out how to work around stuff it becomes a problem.

On a related note, would you use the same method (scenes) for loading and unloading distant objects?
Like unloading small objects, then bigger and bigger ones.

#

Or would you not really do that and just unload the whole section at once in a single scene?

red osprey
#

Well "load time". One of them was a VR demo that had basically zero load time, but transitioning from scene to scene involved matchmaking, which <shrug emoji> when we can find a partner.

#

So they'd stand in an empty room while the matchmaking ran.

#

But they could still walk around, move their hands, etc.

undone coral
#

and nothing bad happened

#

i can never really pin down what people mean by bloated. it is usually a tautology for "i don't like this"

#

if you ban "bloated" as a reason not to use something, there's nothing to what you're saying

red osprey
#

Nothing bad happened? Not even when Unity added it too and broke people's builds?

compact ingot
#

a library duplicate is not "breaking a build"

#

anyone could fix that, does not require special project specific knowledge of the codebase

red osprey
#

Breaking the build process.

undone coral
#

i meant day to day, c# developers and the unity ecosystem uses external libraries and plugins routinely

red osprey
#

And not anyone could fix that. It was an ongoing struggle that lasted years.

undone coral
#

some are bad. but why would i recommend a bad library to my bros on the internet

compact ingot
#

anyone with a chance to actually finish a project must be able to deal with library conflicts

red osprey
#

But the point is why did you waste time dealing with library conflicts if there was a simpler solution?

undone coral
#

isn't that crazy? that's the opposite of what the yavascript developer would do

compact ingot
#

unity is good at making people believe its easy to make stuff with it

undone coral
#

the error message is a little arcane

#

but if you punch it into google the solution is there

red osprey
#

Correct. I use Newtonsoft right now. But that's because I need polymorphism for this specific project. Until that point, Unity's built-in library worked just as good, and it was built in.

compact ingot
#

the builtin one is a joke

undone coral
#

well if you're doing some kind of networked RPC HTTP thing

red osprey
#

If it handles your need, then why would you waste your time managing build dependencies?

undone coral
#

you know, you better start believing in external libraries and codebases, because you're using one

#

something something, the pirates of the caribbean meme

red osprey
#

Lol

undone coral
red osprey
#

Lol

undone coral
#

lol

#

"computer, can i get a Nude Async?"

#

"hi, i'm async, i'm one of your new dancers. and you're gonna love me"

tough tulip
# undone coral hmmm.. well for most of its history many C# developers were adding Newtonsoft JS...

you shouldn't compare Newtonsoft json with unirx because
i) Newtonsoft works with both Unity and non unity applications. Unirx doesnt.
ii) What newtonsoft does, did not exist in c# before. there was no way you can implement it individually and as nicely as them.
iii) Newtonsoft json is a utility. It doesn't determine the programmer patterns you pick. Newtonsoft is abandoned and deprecated? fine. just simply replace the calls to Newtonsoft with another package or your own version of serialization.

its like comparing apple to oranges. totally irrelevant in this conversation

red osprey
#

The point is that, if you're importing a library that can do 20 things, and you need 2, then you are importing 18 things that you need to support but don't need to use. If those 2 things are already handled by something you already have, then you're importing 20 things that you need to support but don't need.

That's okay, but it's quicker and simpler to not do that, unless you have a specific reason.

compact ingot
red osprey
#

That's... not even true at all?

tough tulip
#

if you hate the async/await pattern, there is always IAsyncResult/callback pattern which you can implement, probably what most C# programmers were using before TPL was introduced in .net4
you can easily control the thread from which the callback is being fired.
you can implement error callbacks incase theres an exception/cancellation.
its like you fire a function and forget. when you get the callback, deal with it

compact ingot
#

if you want your code to just do exactly what you need, write it from scratch in C

red osprey
#

That's... also not even true at all?

#

If you're being completely purist, it would be machine bytecode.

#

But, even then, that still doesn't even make sense?

compact ingot
#

maybe you don't want it to make sense to you

undone coral
#

they're useful patterns though

#

it's a big part of its value*

compact ingot
undone coral
#

anyway, i think this is trying to arrive at a definition of bloat, which is uninteresting

tough tulip
undone coral
#

well a lot of people reinvent reactive programming

#

exhibit a: DOTS

#

that's why i advocate it so much. it's a good way to make games

#

DOTS is a lot clunkier than UniRx

red osprey
#

But yeah I mean if you want to use external libraries, then that's cool. If you spend more time doing that then actually solving your problems, initially and over time as you need to support it, especially when multiple people are involved, then you literally wasted time.

undone coral
#

reinventing this stuff is a bad idea

red osprey
#

However, if you saved time, then you saved time, and that's good.

undone coral
#

If you spend more time doing that
you are definitely going to spend more time reinventing valuable stuff from unirx

red osprey
#

You need to make the value judgement whether you're being foolish... and you'll be wrong at times, and that's okay.

undone coral
#

than from like, adding a line to your manifest.json

tough tulip
# undone coral DOTS is a lot clunkier than UniRx

you mean entities? if its jobs you're talkinh about, probably it will stay like that for a long time.
incase of entities, well they are warning beforehand for massive api changes. who knows they might improve

undone coral
#

it's interesting. it sounds like you got it backwards basically. it sounds like there's a belief using the external library is slower than figuring out GetAwaiter, ThrowIfCancellationRequested, SynchronizationContext, the whole async task api just to figure out like, how do make sure it's on the right thread

#

UniTask has a way to guarantee you're on the right thread

#

that's better than the built in ways

red osprey
undone coral
undone coral
#

you started with a question

red osprey
#

I didn't say that???

undone coral
#

knowing stuff from other work
this is what i mean by a more knowledgeable person

#

anyway

#

it's your dime

#

something something, the SCV meme

red osprey
#

I mean it's reasonable to gutcheck whether my experience matches anything weird that Unity does.

undone coral
#

yeah. unity is weird

compact ingot
#

why is it weird?

undone coral
#

it's Flash, written in C#. it predates the stuff aspnetcore developers know and love

compact ingot
red osprey
#

To be clear I wasn't crapping on your suggestion for UniTask. It was a good suggestion for someone that didn't know it exists. But I was asking a specific question, and I wanted to make sure that other people in the channel who did know the answer to the actual question that I asked didn't think that I was satisfied with your answer and not say anything. @undone coral

undone coral
red osprey
#

Like -- if people think you answered it, then I would never get the answer that I needed.

undone coral
#

it's answered

#

although i'm not 100% sure 😦

#

it's such a tricky question

red osprey
#

Nah it's not a bad or whatever. It just kinda blew up.

#

It was definitely a valid suggestion for the assumed root problem.

compact ingot
undone coral
#

imagine if people asked DOTS questions here

#

i'd have to run and hide

compact ingot
#

maybe people think too much in terms of what c# can do and can't and too little about what they want to make happen and what principles get them there independent of whether or not c# can express them cleanly

red osprey
#

@urban warren Oh I forgot to mention... if you do additive loading and unloading, then you need to remember to garbage collect the assets after you unload a level. Unity does this by default with a full level open, but skips it for additive, forcing the user to write Resources.UnloadUnusedAssets() otherwise old scenes will pile up in memory.

#

(I don't know why they didn't just make it a required parameter... do you want to run a garbage collection to find assets to clean up too? true, false?)

#

I mean cleaner API but I'm wondering how many people's games are leaking gigabytes of RAM because of this.

compact ingot
#

most people's games fit entirely into memory, and its only assets, which get reused and not duplicated on each scene load

red osprey
#

To be clear I am aware why it's not done automatically for additive loading. I'm asking why it's left as arcane knowledge rather than, like, a compiler error -- unless you're saying that it's rare enough that it's more harm than good.

urban warren
#

I think I will be reusing most assets over the whole thing so idk how much would actually be unloaded. But it is good to know and keep in mind

compact ingot
cedar ledge
#
public void OnScoreboard(InputAction.CallbackContext context)
{
    switch(context.action.phase)
    {
        case InputActionPhase.Started when IsLocalPlayer:
            scoreboard.SetActive(true);
            break;
        case InputActionPhase.Canceled when IsLocalPlayer:
            scoreboard.SetActive(false);
            break;
    }    
}

vs

public void OnScoreboard(InputAction.CallbackContext context)
{
    if(IsLocalPlayer && context.action.phase is InputActionPhase.Started)
        scoreboard.SetActive(true);
    else if(IsLocalPlayer && context.action.phase is InputActionPhase.Canceled)
        scoreboard.SetActive(false);
}
#

which one do you hate less

remote pumice
#
if(IsLocalPlayer)
{
    switch(...)
    {
        // ...
    }
}

or

if(!IsLocalPlayer)
{
    return;
}

switch(...)
{
        // ...
}

but from your examples, it's the first one

urban warren
compact ingot
#

point is, the IsLocalPlayer is an extremely important condition and should be treated as such, not buried and repeated in each statement

red osprey
#

Yeah. Early exit for IsLocalPlayer looks good. Another alternative is get-only properties depending on how else it's used in code, but I think I prefer wtch28's example over the others.

#

It also probably doesn't matter toooo much. I can understand what every one of these examples does at a glance (without having background knowledge of your codebase).

#

That's kind-of the hierarchy of code structure choices:

  • Easy to read
  • Easy to change
  • Easy to write
    ... in that order. All of them are easy to read in my opinion.
remote pumice
#

Could also get fancy and have a thing that's listening to the input, check if it's LocalPlayer, and only if so, forwards it to some kind of processor, so the part where you're processing the input doesn't even know about Local or NonLocal Players and could be used by either, if ever necessary
Just4fun 😂

red osprey
#

Have some form of finite state machine setup such that it's impossible to hit that code path unless you're a local player. That said, it's easy to over-engineer that (granted it was said "just4fun").

remote pumice
#

simplistically, random naming

class InputReceiver
{
    InputProcessor inputProcessor;
   
    // subscribe / unsubscribe somewhere 

 void OnInputReceived(...)
    {
        if(!IsLocalPlayer) return;
        inputProcessor.ProcessInput(...);
    }
}
class InputProcessor
{
    void ProcessInput(...)
    {
        switch(...)
        { 
            // ...
        }
    }
}

in it's barest form, it wouldn't even need a FSM

cedar ledge
#

ah yes, implementing an InputProcessor for the new unity InputSystem for input, replacing the old Input system (two words)

sonic thorn
#

Is there a way to map raycasts to a 3d object, like say I want to have them shoot out of the object at regular intervals, but change their angle based on the terrain

#

Like every 20 pixels or so a raycast is generated

compact ingot
sonic thorn
#

pixels was the first measurement that came to mind, its not my actual intent on aproaching this

regal olive
#

Okay, I'm throwing my hands up in defeat here. I simply can't figure out how to use Animation Events' Object Reference parameters at all. I've never seen so many NullReferenceExceptions in my life. It's like it's just refusing to read the data. This is poorly documented, how does this work? 😦

molten socket
#

Hi again, everyone. I have a simple issue that I can't seem to solve. I have a large number of gameObjects in a scene that are supposed to have a reference to the next gameObject in sequence. To automate this process of populating all of them, I wrote an editor script. The script works great! When I run it and check all the objects, the references are present. However, if I close unity, switch to another scene and back, or press play, all of the references disappear. Am I missing a SaveScene function or something? I can't find anything like this on the forums or Scripting API!
Here is the script: Thanks!

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class SetupCheckpoints : MonoBehaviour
{

    [MenuItem("Extreme/Fill Checkpoint Data")]
    static void FillCheckpointData()
    {
        Checkpoint[] cps;
        EventManager em = GameObject.Find("ManagerContainer").GetComponent<EventManager>();
        cps = em.checkpoints;


        string message = cps.Length.ToString() + " checkpoints are listed in EventManager. Is this correct?";
        if (EditorUtility.DisplayDialog("Fill Checkpoint Data",message,"Yes, fill data","Cancel"))
        {
            for (int i = 0; i < cps.Length; i++)
            {
                if (i!=cps.Length-1) cps[i].nextCheckpoint = cps[i+1];
                else if (i==cps.Length-1) cps[i].nextCheckpoint = cps[0];
            }
            Debug.Log("Done");
        }
    }
}
molten socket
#

It requires an object as a reference. What do I call it on? Would that be every single object I modify (i in the loop)?

fickle mango
#

I would assume so

molten socket
#

The docs aren't very good on this function. SetDirty isn't defined. What using reference am I missing?

molten socket
#

Okay, thanks. This seems to work!

cedar ledge
#

Is there a straightforward way to tell if a type deriving from Unity.Object is defined by Unity? (I'm guessing checking the type's namespace against Unity's namespaces)

Extra credit: is there a way to tell if it was defined a script that was written by the developer of the project (aka not an asset)?

placid violet
#

use refelction

#

Is it possible to decompress an asset bundle just by using the reference LZ4 decompressor library?

hazy epoch
#

Can anybody help with why I'm getting this error... from the following code snippet.

var Copy = UnitsOutOfLockOnRange;

//Check the time stamp of each unit in this out of range dictionary. 
foreach (KeyValuePair<BaseUnit, float> kvp in UnitsOutOfLockOnRange)
{
   //If X amount of time has passed, remove their lock on status.
   if (Time.time - kvp.Value > lockOnHoldDuration)
   {
      UnitsLockedOnto[kvp.Key].Disable();
      UnitsLockedOnto.Remove(kvp.Key);
      Copy.Remove(kvp.Key);
   }
}

UnitsOutOfLockOnRange = Copy;```
#

The error obviously occurs on the foreach line.

somber tendon
hazy epoch
novel plinth
hazy epoch
# novel plinth you can make a `shallowCopy` of it via .ToList() `foreach (KeyValuePair<BaseUni...

That's funny, because I just typed that up while waiting for a reply...

for(int i = UnitsOutOfLockOnRange.Count - 1; i > -1; i--)
{
   //If X amount of time has passed, remove their lock on status.
   if (Time.time - UnitsOutOfLockOnRange.ElementAt(i).Value > lockOnHoldDuration)
   {
      UnitsLockedOnto[UnitsOutOfLockOnRange.ElementAt(i).Key].Disable();
      UnitsLockedOnto.Remove(UnitsOutOfLockOnRange.ElementAt(i).Key);
      UnitsOutOfLockOnRange.Remove(UnitsOutOfLockOnRange.ElementAt(i).Key);
   }
}

Should work?

novel plinth
#

try it

Your dictionary sorta useless if you decided to iterate it, tbh

somber tendon
hazy epoch
hazy epoch
#

But reverse looping it worked.

#

Thanks.

novel plinth
#

sure, but you lose the O(1) of the dictionary

#

better off with List instead

cedar ledge
cedar ledge
kindred tusk
# sonic thorn Is there a way to map raycasts to a 3d object, like say I want to have them shoo...

If you want to raycast at regular intervals of movement you can track the last raycast position and test how far the object has moved.

[SerializeField] float _raycastMoveDistance = 1f;
Vector3 _lastRaycastPosition;
void FixedUpdate() {
  Move();
  if (Vector3.Distance(transform.position, _lastRaycastPosition) > _raycastMoveDistance) {
    DoRaycast();
    _lastRaycastPosition = transform.position;
  }
}
queen sparrow
#

Hi guys, I have a question about FBX importing. Can I do it and instantiate the FBX as GameObject in runtime?

unkempt nova
#

Yeah, just not directly

queen sparrow
unkempt nova
#

You can't just instantiate models, they have to be part of a prefab. So make a prefab with the model in it, using a mesh renderer

#

Then you can instantiate it at runtime

queen sparrow
#

Thanks for replying 😄 But that's the problem, I just want our 3D artists uploading their stuffs directly on the server and instantiating models on client.

#

It seems technically impossible then...

unkempt nova
#

I'm sure it possible, just harder

flint sage
#

I'm sure you can get some library to import FBXs at runtime and then convert them to a Mesh and generate a gameobject that renders it

#

Is it easy? Probably not. Is it worth it over other workflows? Probably not either

#

I wouldn't do it unless you have no choice

#

Also look into things like Addressables, which do let you update content at runtime easily but your artsts will still have to do some work in Unity

queen sparrow
#

Yeah, you're right.

#

Silly thing is our artists favor Unreal Engine and... you may know the rest

tough tulip
# queen sparrow Thanks for replying 😄 But that's the problem, I just want our 3D artists uploa...

having a server makes things easier. you can write unity editor scripts in server to convert the fbx to asset bundle. and load the asset bundle on client if performance matters to you.
if you dont want all that hassle and are dealing with multiple platform, your best bet is to find some runtime FBX importer from asset store. runtime fbx importing will be hassle free, but loading performance and memory footprint will never be as an asset bundle

queen sparrow
#

Thanks, malloc. Your advice's very helpful. But can Unity execute Editor's scripts in command line? Or I need an opened Unity Editor on the server?

tough tulip
#

its usually weird mapping fbx textures and materials correctly and automatically and also use the correct shader for each material (like transparent ones)
you need to handle it yourself if you're going with editor approach.

you can also try GLB format if you artists are making the models . its not standard yet, but you wont have issue mapping the texture and materials and shaders. most unity glb importers have their own shader, you can try Gltfast to import GLB both in runtime and in editor

flint sage
frozen imp
#

@queen sparrow Not gifs or memes, please.

mint sleet
#
    public List<RoleDto> GetOrgAdminUserDtos(string userId, string orgId)
    {
        using (var context = new EfVrCloudContext())
        {
            var result = from userOperationClaim in context.UserOperationClaims
                join operationClaim in context.OperationClaims on userOperationClaim.OperationClaimId equals operationClaim.Id
                join orgAdmin in context.OrganizationAdminUsers on userOperationClaim.UserId equals orgAdmin.AdminId
                where orgAdmin.OrganizationId == orgId
                select new RoleDto()
                {
                    Id = operationClaim.Id,
                    RoleName = operationClaim.Name
                };
            return result.ToList();
        }
    }```
#

Hello folk

#

this query returns an incorrect value.

#

I could not figure it out why

novel plinth
frozen imp
weary stag
#

Anyone know what could be causing this?

weary stag
#

Ah I just realized that I forgot structures are value types and need to be passed by reference if edits to them should be done correctly.

daring pelican
#

Hey guys, I am looking for materials on advanced AI, can someone recommend anything?

#

There's lots of stuff on YouTube that's called "advanced AI" that is quite basic, I want to go down that rabbit hole

unkempt nova
#

Look into GOAP if you haven't yet

#

That's a fun one

daring pelican
unkempt nova
#

Well, if you intend to add AI, sure. It was used in FEAR, for its AI and it was a good AI

#

Incredible AI

#

GOAP is Goal Oriented Action Planning, it uses pathfinding to find a series of tasks to achieve a goal

#

So their AI would literally lay traps for you. One enemy would run away, to lead you into an ambush, etc. Not scripted, just generated by the planner

daring pelican
#

Thanks. I remember FEAR. Yeah something tells me that I'll have to stick to behaviour trees though

unkempt nova
#

Depends what you wanna do

daring pelican
unkempt nova
#

Yeah, don't need any sort of advanced AI at all for that

#

Trees or a FSM should be fine

daring pelican
#

That's what I thuoght, thanks for setting my mind straight!

flint sage
#

Just having GOAP doesn't mean your AI is good 😛

#

Most techniques can end up with good AI but it's more of a design question than an algorithm question

compact ingot
#

its also been long known in AI research that very simple, reflex actions on agents can create very interesting complex group behaviour, think bees, ants and soccer robots (reflex action = complexity of the type move forward if environment smells nice)

fossil bloom
#

Hello, does anyone know if primitive types on GPUs are deterministic across all GPUs? Meaning, given the same code used on different GPUs, it would produce the same data with no deviation to values. If not, is it in some way possible to produce a custom struct which would have this quality?
E.G double, float, half, int.

red osprey
#

One fun AI technique is creating a list of "event" structs (ex: for stealth action games). They can sift through literally everything they remember and make appropriate choices. Really simplifies bug-crushing (ex: if the user tries to abuse AI by forcing two known, conflicting states), sharing information (if two NPCs get close together, and one has an event that they want to share, then they can do a conversation animation and the listeners now have that struct), or forgetting things (just delete the event).

But, yeah, completely not relevant for an arena shooter.

sage radish
red osprey
#

Some keep half, but at reduced performance. Some keep half and have a performance increase.

#

GeForce 10 series does 16-bit floats at 1/64th the throughput of 32-bit floats.

#

Turing and later should all be 2x faster than 32-bit though. Ah... no... GeForce 30 are 1 to 1 for some reason??? Turing is 2x, though.

sage radish
#

This seems to suggest that half is automatically converted to float in DX10+ by the HLSL compiler and the only possibility to use 16-bit floats is with min16float, which is still not guaranteed 16-bits.
https://therealmjp.github.io/posts/shader-fp16/

#

(they boldened it, not me)

red osprey
#

I should also mention that, to some extent, no-one has any control over what the GPU executes. The driver can single out your application and replace your shaders out from under you.

hexed meteor
#

Can anyone recommend me a really good advanced tutorial on YT to create complex AI with a finite state machine?

#

I've watched countless but they all 'feel' wrong, clunky, convoluted or just plain too simple.

compact ingot
#

you would need a different model to implement it, like a BT, utility functions, planners, ML, ..., FSMs can be part of it, but they have a tendency to get unwieldy/complex rather quickly

hexed meteor
#

interesting, yeah feels like that's what I'm struggling with

#

let's say my needs are not that complex though, I just suck at keeping my sight on the big picture

#

do you have any FSM implementation that you can whole heartedly recommend a video for on YT ?

compact ingot
hexed meteor
#

Thank you! I'll check that out!

compact ingot
#

what exactly are you struggling with in regard to FSMs that you hope a YT course could solve?

hexed meteor
#

I just need handholding by yt video, I'm not experienced enough yet to fully juggle things like abstract classes, dictionaries etc

#

I can write a reasonably good state machine for a single enemy/npc but I'm trying to figure out an implementation that allows me to use the same code for a multitude of monsters

#

while still giving some of them unique behaviors that blend in neatly

#

basically a really solid scaleable implementation is what I'm after

compact ingot
#

sounds like you need to work on your c# and overall programming fundamentals

hexed meteor
#

yeah I probably do

compact ingot
#

wish there was a single thing that could be recommended to everyone to get them to a point where they don't feel limited by their lack of knowledge about programming in general and c# in particular

compact ingot
#

"the world"

steep skiff
#

tbh, if you don’t know how to do something, just read the documentation on it or look up a yt video on it

compact ingot
#

that doesn't work for complex, custom systems and your own ideas

steep skiff
#

you said fundamentals

sour marlin
#

Hello all,

Not sure if this is #archived-code-advanced worthy or not but here we go. Anyone know how I would go about getting access to an fbx's animation clips in an editor script not during run time? I've tried using AnimationUtility.GetAnimationClips(Object) which only works at runtime. I'm on 2019.2.19f1.

steep skiff
#

of course if you’re trying to make your own thing, you have to make it

compact ingot
#

maybe we have a different definition of what fundamentals are

steep skiff
#

the person above was talking about dictionaries and abstraction

#

one is a fundamental data structure, the other is fundamental to OOP in general

stone swallow
#

hi guys, im currently working on an Optimized Center of Rotation skinning solution for unity, and right now my bottleneck is this loop:

for (int j = 0; j < bones.Length; j++)
            {
                boneMatrices[j] = bones[j].localToWorldMatrix;
                q[j] = bones[j].rotation;
            }

with 144 animated characters, i get about 100 fps. using standard skinning, i get about 130 fps. about 39% of the frame time is used just in that loop. does anyone have any ideas for what could be done to improve this?

#

the loop is setting up arrays to set the data on a compute buffer for use with the compute shader

sage radish
#

You can use Jobs and Burst for this most likely. C# jobs can write directly into compute buffers with ComputeBuffer.BeginWrite.

#

You can use TransformAccessArray and IJobParallelForTransform to iterate over the bone transforms while still being Burst compatible.

#

I think you could easily get 100% better performance with Burst in this scenario.

stone swallow
#

i dont have much burst compiler experience, what kind of performance boost do you think i could get with this?

#

well it obv depends on core count but you get what i mean

sage radish
#

Like I said, I don't think 100% improvement is unreasonable.

#

So, double the performance

stone swallow
#

oh wow with that i could outperform the unity skinned mesh renderer

stone swallow
#

thank you for your suggestion sir

stone swallow
# sage radish You can use `TransformAccessArray` and `IJobParallelForTransform` to iterate ove...

i just read on the unity forums that IJobParallelForTransform will operate on the same thread if they have the same parent : https://forum.unity.com/threads/ijobparallelfortransform-15000-transforms-executed-on-single-job-thread-any-hints.537723/

#

since im using this in the context of writing a new skinned mesh renderer, and the bone hierarchy is well, a humanoid skeleton, are there still performance improvements to be seen?

sage radish
#

No, I'm wrong. It's using the root parent.

stone swallow
#

the compute buffer writing is ~5% of the cpu time, while it would be nice to get down the main thing is the loop where i get the bone matrices

#

ill give it a shot and see how much it helps, thanks again

undone coral
stone swallow
#

both dummys have the same pose, you can see the volume preservation in action

#

most of the logic isnt my work, but further developing and optimizing the project with permission from the original author

undone coral
stone swallow
#

im uploading to github when its done under mit

undone coral
#

what maya calls muscles

stone swallow
#

areas around wrists and elbows in FPS games get a big benefit

undone coral
stone swallow
undone coral
#

no it looks really good

stone swallow
#

there are other alternatives, such as the popular DQS algorithm, which already has a public project on github

#

that however comes with its own issues, such as bulging artifacts

undone coral
#

most of the 3d humanoid models i work with that aren't pre-made for games come from 3d scans

#

for very narrow cinema effects. so they look good but they are not rigged for animation in a meaningful way

stone swallow
#

ah yea this system still uses standard setup for rigged characters

#

characters need to be weight painted and rigged

undone coral
#

yeah my memory is in maya you have to do things like painting the muscle groups

stone swallow
#

right you still have to do that here

#

animations do work btw i just dont have a video yet

undone coral
#

i wonder if in photogrammetry workflows they'll figure out how to shoot people in different poses

#

and infer the muscles that way

stone swallow
#

there are methods that do what you desire

undone coral
#

what people want is money goes in -> rigged model comes out

#

lol

stone swallow
#

"voxel heat diffuse skinning"

#

it provides pretty good skinned results out of the box, which can then be tweaked

undone coral
#

this stuff doesn't translate to unity right?

stone swallow
#

i learned about it when researching for this project

undone coral
#

maya has a similar builtin but it's worse than this

stone swallow
undone coral
stone swallow
#

if you find it interesting id appreciate a star on it. while ur there u may as well check out my normal map inverter or the gpu instancing tool

undone coral
#

"Sky in your Eye? Flip your Y"

#

needs some work...

#

very close though

#

you know it's wrong when there's sky reflecting inside the edges of a flat surface

#

lol

stone swallow
stone swallow
sage radish
sly grove
lunar tapir
#

My bad, didnt see it in the rule section I was reading but it was the wrong one. Just difficult to find someone for a 1:1

stone swallow
quartz stratus
#

I have a code optimization question. When iterating over many elements in a List with a for loop, where you have to check a condition against certain properties of the element, is it faster to cache the element in a local variable or index into the List every time?

Example:

using System.Collections.Generic;

public class Example
{
    // Assume this is populated with many elements.
    private List<SomeObject> listOfObjects;

    // Method 1
    // Index into the List once and create a local variable (someObject).
    public SomeObject GetObject1(float someValue)
    {
        for (int i = 0, count = listOfObjects.Count; i < count; i++)
        {
            var someObject = listOfObjects[i];

            if (someValue >= someObject.Min && someValue <= someObject.Max)
                return someObject;
        }
        
        return null;
    }
    
    // Method 2
    // Index into the List every time.
    public SomeObject GetObject2(float someValue)
    {
        for (int i = 0, count = listOfObjects.Count; i < count; i++)
        {
            if (someValue >= listOfObjects[i].Min && someValue <= listOfObjects[i].Max)
                return listOfObjects[i];
        }
        
        return null;
    }
}

public class SomeObject
{
    public float Min;
    public float Max;
}

For the sake of the question, assume that this code is running every frame.

sly grove
#

As a general rule, caching it in a variable always has the potential to be faster, and will almost never be slower.

granite viper
#

also not caching it is uglier

sly grove
#

it's hard to say exactly because there are variables at play here like compiler optimizations

granite viper
#

to read, I mean

sly grove
#

I agree with that - but that part is reasonably subjective.

granite viper
#

nah, totally objective truth

#

😄

sly grove
#

When you take this code at face value - the indexer being called fewer times naturally will be faster, since the indexer of a list is a method.

#

It's possible that Roslyn optimizes that out though so who knows for real without doing some ILSpy

granite viper
# granite viper also not caching it is uglier

btw the reason this is actually important and not a pithy answer is because you spend way more time reading code than writing it, so it is good to make sure your code is as easily readable as possible

granite viper
#

or am I being dense

granite viper
#

turns out I'm being dense

#

gtk

sly grove
#

To be fair it used to use Mono for some time

granite viper
#

ok

#

glad I'm not totally hopeless

#

really makes MonoBehaviour look even dumber of a name doesn't it

sly grove
#

lol

#

yes

#

Given that Mono is now merely one possible scripting backend option, and not the "flagship" one.

hazy gazelle
#

does anyone know how to create a grappling hook in VR?

granite viper
#

good thing it's not stuck as one of the most fundamental concepts in Unity or anything

quartz stratus
#

thank you both for the insights!

fresh salmon
hazy gazelle
fresh salmon
#

Your question is way too broad

granite viper
#

it's not a great question, which is why no one is helping you

sour marlin
granite viper
sour marlin
#

Awesome, thanks! I'll give it a shot.

granite viper
#

gl

#

@sour marlin if you need to get the Importer of your asset, use AssetImporter.GetAtPath

fresh salmon
granite viper
#

but for indexers I wouldn't be surprised if it doesn't optimize it out since there can be side effects of accessing an indexer in C#

fresh salmon
#

Lol true

private int _counter;
public T this[int index]
{
  get {
    _counter++;
    if (_counter > 3)
      throw new InvalidOperationException("This collection is now tired. Please use another one, thank you.");
    return ...
  }
}
granite viper
#

haha

#

reminds me of INTERCAL

fresh salmon
#

Oh that language

#

It's the one you have to say "please" the right amount of times otherwise it doesn't compile right

granite viper
#

yeah

fresh salmon
#

lmao even the user manual for the language is a complete joke

3.4.3 Precedence
Precedence of operators is as follows:¹
(literally nothing on the page)

(at bottom of page)
¹ Keep in mind that the aim in designing INTERCAL was to have no precedence

#

This precedence (or lack thereof) may be overruled by grouping expressions between pairs of sparks (’)
or rabbit-ears (")

sour marlin
undone coral
#

if it's a struct you will get copies of it, which is probably not what you want

sour marlin
red osprey
# quartz stratus I have a code optimization question. When iterating over many elements in a List...

So... there's a lot to unpack here.

First, caching the value is just caching the memory address where to get the value, because SomeObject is a reference type. The memory addresses are stored in order once you get into listOfObjects' backing array, which should be in cache, especially for two consecutive accesses of the same value, which the compiler might eliminate anyway. Actually going into someObject to get Min and Max (which are value types) is the expensive part, because that's at some random place in memory (again, SomeObject is a reference type).

That fetch to get Min and/or Max will be ~200 cycles every iteration.

That said, chances are, fetching listOfObject[i].Min has also fetched listOfObject[i].Max, because they're probably on the same cache line (value types). An Intel or AMD CPU cannot physically request less than 64 bytes of memory, so any request gets all the 64-byte aligned memory before and after your value. (Apple M1 is 128 bytes for cache line size.) So even though you paid 200 cycles to get Min and or Max, you will probably have got them both, so you should only pay that 200 cycles once.

In other words, the thing that's cached is likely a tiny percentage of the overall work being done per iteration.

Also, "every frame" isn't the important thing at this level. Computers do about 4 billion cycles per second per core these days. If you're just talking a hot loop that only happens one time per frame (if that script is on hundreds of objects, then no, but if it's just one object...) then it's not going to be a big issue until we're talking about, like, tens of thousands of elements (or we're talking about a SomeOtherObject that has a bunch of reference types on it, because you're then hopping multiple times every element, which is ~200 cycles each hop).

And even if it was a big issue, you'd probably run into accessing the values of SomeObject before you run into problems finding out where SomeObject is. In which case, you'd make SomeObject a struct (which is a bit of a pain in the butt to work with).

#

Long story short -- these sorts of issues are highly unlikely to be your bottleneck. You're almost definitely going to hit an issue somewhere else. Use the profiler.

#

Btw: These sorts of questions are great. Optimization is very arcane, so ask ask ask.

stone swallow
# sage radish You can use Jobs and Burst for this most likely. C# jobs can write directly into...

so im still on this, this is where im at:

[BurstCompile(CompileSynchronously = true)]
        private struct SetBuffersJob : IJobParallelForTransform
        {
            [WriteOnly]
            public NativeArray<float4x4> BoneArray;
            [WriteOnly]
            public NativeArray<Quaternion> RotationArray;
            public void Execute(int index, TransformAccess transform)
            {
                BoneArray[index] = transform.localToWorldMatrix;
                RotationArray[index] = transform.rotation;
            }
        }
boneBuffer.EndWrite<Matrix4x4>(bones.Length);
            _boneArray = boneBuffer.BeginWrite<float4x4>(0, bones.Length);
            //var nativeArrayMatrix = UnsafeUtility.As<NativeArray<Matrix4x4>, NativeArray<float4x4>>(ref _boneArray);

            qBuffer.EndWrite<Quaternion>(bones.Length);
            _rotationArray = qBuffer.BeginWrite<Quaternion>(0, bones.Length);
            //var nativeArrayQuaternion = UnsafeUtility.As<NativeArray<Quaternion>, NativeArray<float4>>(ref _rotationArray);
            //Profiler.EndSample();
            gatherMatrixJob = new SetBuffersJob()
            {
                BoneArray = _boneArray,
                RotationArray = _rotationArray
            };
            gatherMatrixJobHandle = gatherMatrixJob.ScheduleReadOnly(transforms, 128);
#

it seems what its doing now is making copys of the buffers rather than sharing. trying to do it with pointers gains 20 fps but crashes unity

#

is there a way to do the setting of the compute buffer from directly within the job so i dont have to make so many duplicate buffers?

undone coral
undone coral
stone swallow
#

ah

meager kite
#

ok this is really annoying

#

i have a vector named X

#

its value is here

#

but when i debug it or compare it to something else, it turns into this

#

and its completely messing up my code

#

how can i get the script to use the actual value of x, not this rounded one

stone swallow
#

u can try debugging like this

#

Debug.Log($"{someVector.x} {someVector.y} {someVector.z}");

novel plinth
#

or you can simply do this Debug.Log(someVec3.ToString("F4"));

unkempt nova
#

So I'm trying to find tiles in a grid within range of a given position. I'm doing this recursively, by starting with a point, getting its neighbors, and recursing into them, subtracting from range until range ==0, then adding to a returnValue list.

This is getting all of the nodes, but I was trying to get only the outer tiles. i.e. the tiles at max range, not in between. I figure there's a way to do this via the recursion, and I thought checking range = 0 would do this for me, but it doesn't. Makes sense why, because it's finding all possible paths, but I don't want them.

Ideas?

public static List<GraphNode> GetNodesWithinRange(Pawn pawn) {
        
        List<GraphNode> returnValue = new List<GraphNode>();
        Recursion(pawn.CurrentTarget.transform.position, pawn.AttackRange);
        void Recursion(Vector3 nodePosition, int range) {
            Debug.LogFormat("Recursion, range: {0}", range);
            var neighbors = GetNeighborsFromPosition(nodePosition);
            foreach (var neighbor in neighbors) {
                if (range == 0) {
                    if (!returnValue.Contains(neighbor)) {
                        returnValue.Add(neighbor);
                    }
                }
                else {
                    Recursion((Vector3)neighbor.position, range - 1);
                }
            }
            
        }

        return returnValue;
    }
long ivy
#

your code looks like it will just return all of the tiles in the grid regardless of distance to me

undone coral
#

however, if the grids were huge, you would connect them with weighted paths corresponding to the distance they are from the tile

#

or... you could read them directly, since the shape of the circle known ahead of time

#

all of these are good solutions

unkempt nova
#

This is different. There are just nodes, with neighbors

#

But yeah, distance does make sense. Need to check if current distance = range. Thanks

#

Cool, just made it not recurse to neighbors that weren't further away from target than current node

undone coral
#

take a look at breadth first search 🙂

#

you are reinventing it

#

it's nbd

#

you're actually doing a mix of BFS and DFS

#

it's all the same though

#

how's the game?

unkempt nova
#

Yeah, I know what it is, that's why I'm thinking I can just have the recursion handle this for me

#

Still not working quite right, but close

#
public static List<GraphNode> GetNodesWithinRange(Pawn pawn) {

        List<GraphNode> returnValue = new List<GraphNode>();
        Recursion(pawn.CurrentTarget.transform.position, pawn.AttackRange);

        void Recursion(Vector3 nodePosition, int range) {
            Debug.LogFormat("Recursion, range: {0}", range);
            var neighbors = GetNeighborsFromPosition(nodePosition);
            foreach (var neighbor in neighbors) {
                float thisDistance = Vector3.Distance(nodePosition, pawn.CurrentTarget.transform.position);
                float neighborDistance = Vector3.Distance((Vector3)neighbor.position, pawn.CurrentTarget.transform.position);
                if (neighborDistance <= thisDistance) continue;
                if (range == 0) {
                    if ( !returnValue.Contains(neighbor)) {
                        returnValue.Add(neighbor);
                    }
                }
                else {
                    if (neighborDistance > thisDistance) {
                        Recursion((Vector3)neighbor.position, range - 1);
                    }
                }
            }

        }

        return returnValue;
    }
undone coral
#

you have to do bfs directly

unkempt nova
#

Thought that's what this was because I'm only doing something if range is 0

undone coral
#

when i need to do BFS i truthfully go directly to

#

the textbook

#

CLRS

#

there is also a linq BFS

#

guava has it

formal rover
#

Hello,

I'm trying to use mapbox and photon to spawn GPS player location in a level. I'm trying to find a way to do this with mapbox and heard that I may have to use mapbox conversions, but I don't think I understand how to go about doing this correctly. Any help would be appreciated.

undone coral
formal rover
raw schooner
#

anyone know at all if it's possible to return a uint8_t* from unmanaged code and marshal it into a byte[] in c#?

#

i've tried [return: MarshalAs(UnmanagedType.LPArray)] but that doesn't seem to work

#

(complains about invalid managed/unmanaged type combination)

mint sleet
#

Hello Folk

#

Is it possible to turn off some of the properties coming from derived classes?

#

For example I have
ClassA:Base
ClassB:Base

#

Base

#

My base class has a property of string "Name"

#

both my classess will inherit Base but I do not want to see that property in the ClassA

#

Is it possible?

novel plinth
#

looks like a code smell to me

#

if the properties are virtuals I guess you can do it like this

public override string someStringProps
{
    get
    {throw new NotImplementedException();}
    set
    {throw new NotImplementedException();}
}
#

and if they aren't virtuals you can use the new keyword public new someStringProps, then trow the NotImplementedException

#

I don't recall I've ever used this in such scenario, but ..ugh

sly grove
#

You need to refactor a bit.

#

Perhaps with another level of inheritance, or perhaps by ditching inheritance entirely.

tough tulip
raw schooner
#

Yeah, i figured

#

Thought there'd be a shorter way

royal burrow
#

Anyone here experienced in using Photon for making multiplayer FPS games?

sly grove
royal burrow
#

The programming is giving me an aneurysm

sly grove
#

You might have bitten off more than you can chew if that's the case and you're trying to make a networked multiplayer game

hazy gazelle
#

hey can someine help me with a grappling hook vr script?

tribal pivot
scenic forge
#

Anyone has used source generator in Unity?

#

The manual (https://docs.unity3d.com/Manual/roslyn-analyzers.html) says:

  1. Go to Select platforms for plugin and disable Any Platform.
  2. Go to Include Platforms and disable Editor and Standalone.
    Do they mean to disable everything? If my project is for mobile (Android/iOS) shouldn't I disable those two as well?
tribal pivot
#

Disable everything

#

Because it generates the source in editor time, not in runtime.

scenic forge
#

Cool, that's what I thought as well.

#

Can I access things like AssetDatabase in the SG?

tribal pivot
#

No, its a DLL you compile outside of Unity itself.

I havent used it that much, i guess you could reference the relevant UnityEditor DLL's in your source generator.

#

But i dont know if that will work, i kind of doubt it.

scenic forge
#

Apparently someone said they were able to reference and debug log stuffs, so I assume it works.

#

I'm just wondering if there's a better way to reference Unity dlls besides copying and pasting from the main Unity project it generates, and those paths seem hardcoded and not suitable for version control.

tribal pivot
#

How ive used source generators is by making some C# code in Unity itself, in an custom editor. And then start the source gen, read out that code and compile it

#

That way i can use assetdatabase or anything else from the Editor

scenic forge
#

Similar, currently I have it as an editor script that generates the C# code and write directly to file, but it's a bit ugly (and I have to remember to run it manually every time)

#

Another question, the SG dll I built is just IL and platform agnostic right?

#

I need to build my game on Mac (not my dev OS) for iOS, don't want to run into trouble later on.

tribal pivot
#

I think so yes, its compiled in editor time. Just like how your own code is compiled

#

best check it though

scenic forge
#

Welp I gave it a try and couldn't get it (access to Unity editor stuffs) to work.

#

Maybe there's a way to but I think I'll just stay with an editor script.

#

Since I'm only reading stuffs, I guess if I really want to, I technically could read and parse all the relevant Unity files myself and do processing from there.

#

But that just doesn't seem worth it, plus SG is such a pain to debug.

#

I guess I'll just remind myself to manually run the editor script every time instead.

red osprey
# raw schooner anyone know at all if it's possible to return a `uint8_t*` from unmanaged code a...

Create a byte[] array in C# that's the correct size. It appears as a raw pointer in C code, and C# guarantees that it will not move the backing memory while the C function call is occurring, so you don't need to do any GCHandle pinning bullcrap.
Note: The type must be blittable. uint8_t is. see: https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types

byte[] myBuffer;

//...

[DllImport("libWhatever")]
internal static extern int GetSizeOfThing();
[DllImport("libWhatever")]
internal static extern void WriteToByteBuffer(byte[] argBytes);

//...

void myFunction()
{
  // This is a slightly more complicated example where you don't know
  // The size of myBuffer until it's too late. In this case, you need
  // to make two calls, one to let C# allocate an appropriate buffer, 
  // and one to fill it.
  // If you already have an unmanaged buffer of uint8_ts, then memcpy
  // on the native side within the implementation of WriteToByteBuffer.
  myBuffer = new byte[GetSizeOfThing()];
  WriteToByteBuffer(myBuffer);
}
raw schooner
#

No I, I know

#

Thanks though

red osprey
#

Ah I missed malloc's message sorry.

raw schooner
#

I was already aware of it beforehand, just wished I could do it all in one call without passing a size

red osprey
#

Nah, the GC needs to own the memory.

#

Well I mean one trick that we did in a project @raw schooner was preallocate a byte[] array, and passed the pointer and the size of byte[] into the C function call. If the buffer was big enough, then it would return true and write to byte[]. If it was too small, it would return false. We reallocated and tried again. It helped us because we were looking for messages over and over again.

(In our case, the message knew its own size, and we always had enough buffer to get at least that much of the message, so we didn't need to say how many bytes there were in the return value... in most cases you'd probably want to return an int with size to know what to resize to, or negative for failure... or pass an int[] with a single element for size in another parameter lol)

tribal pivot
#

Yes, very. Why would you tag me?

raw schooner
#

I mean I'd also ping the people I know I can get the most competent information from

shadow seal
#

You'd ping people randomly against the rules?

#

Doesn't sound very smart to me

raw schooner
#

And who said i was smart 😎

deft palm
#

my aipath is screwing up my addForce script

#

i have to remove and re-add my aipath component

#

everytime i change something

#

else it wont do the addForce

gray pulsar
deft palm
#

im just using the built in aipath script

gray pulsar
#

Like nav mesh angents?

deft palm
#

only adding the component to use it

#

literally AIPath2D

gray pulsar
#

I've never heard of that and didn't see obvious docs in a Google search. Are you sure it's built in? Can you link docs?

#

But if it moves your character's, I'd bet that it's incompatible with the physics system (just like nav mesh agents) and you can only have one active at a time

deft palm
#

it works fine once i reset it

#

but i have to reset it everytime i change something

gray pulsar
#

Physics only works if everything moving your objects are doing it via physics. Can't say for sure without seeing the package, but 90% chance it's not moving objects via physics and that's your problem.

If you deactivate the ai, apply a force (change velocity via physics), then reactivate it, you only have one system controlling it at a time so it should be okay. But I wouldn't expect collisions to work, for example.

deft palm
#

i have this in my ontriggerenter

#

other.GetComponent<Pathfinding.AIPath>().isStopped = true;

native nebula
#
public void ManageSprites()
{
    if (Grid.GetLastEntity<EntityBase>(new Vector2Int(Position.x, Position.y + 1)) is EntityWallBrick
        &&
        Grid.GetLastEntity<EntityBase>(new Vector2Int(Position.x, Position.y - 1)) is EntityWallBrick
        )
    {
        SetEntitySprite(Resources.Load<Sprite>("Sprites/Tiles/Building/wall extension"));
    }
}```

So I have this method here. ``Grid`` is a custom class that controls the games grid and manages tiles (2D unity game). GetLastEntity returns the last entity on that tile determined by their Z-priority. Here, I'm trying to automatically update the texture of a tile (UI image) by detecting the north and south sides. At the moment I am running this in Update, but it's expensive for performance. 

Any recommendations for how I can improve performance?
sly grove
#

Is there any reason you need to do it every frame?

native nebula
#

I need to check whenever there's a new neighbor or if one was deleted by the player

sly grove
#

And is this being done on every tile in the game every frame?

native nebula
#

not every tile, only 4 different types

sly grove
#

and only on the tiles that were added/deleted and their neighbors

native nebula
#

yeah I tried doing it whenever the player adds, but they're added at the same time

sly grove
#

what's added at the same time

native nebula
#

like if the player selected multiple tiles to place down this tile, those tiles are replaced by this tile at the same time

#

in a for-loop though

#

ill show

#
// Multi-Tile Building
if (Input.GetKeyUp(KeyCode.Mouse0))
{
    if (!isOverUI)
    {
        for (int i = 0; i < SelectedEntities.Length; i++)
        {
            if (SelectedEntities[i].Name != "GhostEntity")
            {
                SelectedEntities[i].GetComponent<Image>().material = null;
                BuildTileAt(SelectedEntities[i].Position);
            }
        }
...
sly grove
native nebula
#

BuildTileAt handles the creation of new tiles in a case-swotch

native nebula
#

yeah

#

its just a matter when

sly grove
# native nebula oh okay

basically the last line(s) of BuildTileAt should be running those checks or calling another function that does

#

or firing an event that triggers those checks

native nebula
#

yes that's where I had it

#

but for-loops are done in 1 frame right

#

or is it a new frame after each iteration

sly grove
#

everything is done within one frame

native nebula
#

right

sly grove
#

unless there's a coroutine with a yield statement

#

oh I think I see what you're saying - you want to do the checks only after all the changes are made?

sly grove
native nebula
# sly grove then you would track all the tiles that changed in this loop, and do another loo...
case CurrentTileState.S_Wall1:
    if (Grid.GetLastEntity<EntityBase>(position) is EntityWallBrick)
    {
        return;
    }
    else
    {

    EntityWallBrick S_Wall1 = Grid.Create<EntityWallBrick>(position);
        GetEconomy.CurrentExpenses += WallCost;
        AllWalls.Add(S_Wall1);
        S_Wall1.ManageSprites();

        return;
break;
    }```
So I have this for the BuildTileAt method, it's a case switch on whatever the player selected
#

and this is the building process for it

#

you can see the texture doesnt change if there are north and south neighbors

sly grove
#

Is there a good reason you're building this from scratch? Unity's Tilemap system has a thing built in for this

native nebula
#

it's already fully integrated, I'm just implementing some new features

native nebula
#

i figured out an inexpensive way

#

ill just check if it has that texture in the first place, if it doesnt and it has a north/south neighbor, i set the texture

#

so that way its only if there's no north and south neighbors, which should only be for like, 20 or so tiles

undone coral
#

and the tiles have rules

#

?

#

like if i'm the top of the brick it's this texture, and if i'm a line segment brick it's this other texture?

undone coral
#

then it's Solved

undone coral
native nebula
native nebula
undone coral
#

does this make sense?

native nebula
#

up until prepend

undone coral
#

okay

native nebula
#

prepend means...

#

get last in stack?

undone coral
#

i changed it

native nebula
#

okay

#

yeah I get that

undone coral
#

if you have adjacency based rules put them all in one method

#

or call the appropriate method on the tile itself

#

it's upt o you how to organize it

#

but keep adjacency versus other kinds of rules distinct

#

so that you can reason about how to update the tilemap while it's being painted

undone coral
native nebula
#

yeah that makes sense

undone coral
#

before you go further

#

instead of Input which is dead

native nebula
#

do they plan on deprecating Input?

undone coral
#

you can use event system on sprites

#

use Physics2DRaycaster

#

boom that's it

#

i'm nto sure why they don't explain that better

native nebula
#

they dont have any colliders

undone coral
#

well they do, you're just setting up their colliders metaphorically in your own code 🙂

native nebula
#

UI images have colliders?

undone coral
#

no i mean

#

when you use Input.Get... and you check bounds and stuff

native nebula
#

right

undone coral
#

well, you are doing colliders. not Colliders but colliders

#

you don't need to do that period though

#

if your tilemap is UGUI it would just work

#

it doesn't need a collider

native nebula
#

perhaps then

#

thank you @undone coral

scenic forge
#

Debugging SG really sucks tbh.

native nebula
#

SG?

scenic forge
#

Even outside Unity.

#

Source generators.

misty glade
#

Anyone have feedback on best practices for laying out a prefab and locating child objects for use in the script?

In the past, I've exposed the game objects but put them under a header called "internal" but I don't like this since .. if anyone removes a reference while using the prefab, it'll break (potentially at runtime, in non-obvious ways).

I could use Find by name (too slow, if I'm creating lots of the items, which I am) or GetChild by index (which also depends on the user not accidentally drag/drop/reordering the children).

Any feedback? Example progress bar in image.

Also, followup - this particular prefab has 4 images - a left and right "cap" and a middle foreground/background. I'd love to have a public Image field in the parent (and then programmatically set the image of the appropriate child object). Any downsides to that? I'm wondering if my prefabs are going to "do anything funny" by having multiple references to one Image.

grim oxide
#

I have 5 properties of the same type with very similar purpose (i.e. 5 inventory slots). I have an operation that is performed when one of these properties is set. It's the same operation each time, the only variation being which of the properties is changed.

I cannot extract this operation to a function without using pointers. Pointers are gross and apparently not reccomended in Unity. I know I can make an "inventory slot" object with the logic in there to wrap the property's current type, but I'd like to avoid extra objects for a strictly cosmetic code change. Are there other options? 🤔

#
        private ItemState _slotFeet;
        public ItemState SlotFeet
        {
            get => _slotFeet;
            set
            {
                var old = _slotFeet;
                _slotFeet = value;
                if (old != null)
                {
                    _inventory.GiveItem(old);
                    OnUnequip.Invoke(EquipSlotType.Feet, old);
                }                    
                if (_slotFeet != null) OnEquip.Invoke(EquipSlotType.Feet, _slotFeet);
            }
        }
#

Here's the feet slot, for instance. This code is identical in the other slots, but for _slotFeet being a different backing field

#

Without pointers, I cannot make a method that takes the backing field as a parameter

#

This is a bit of a blind spot for me with C# and without pointers I'm not sure what you're supposed to do 🤔

misty glade
#

What's wrong with using a collection to access them?

grim oxide
#

A wrapper object seems like a really lame answer 😛

misty glade
#

public Dictionary<SlotType, ItemState> Inventory;

grim oxide
#

Dictionaries for state in unity? moon2WUT

#

I'd rather not dance with custom serialization for this, that's far worse

misty glade
#

I mean, it doesn't seem like you're tracking state here, but instead placing items in slots..?

grim oxide
#

What's in the slot is state...

#

Is it not? quinThinking

misty glade
#

I mean, not really? You have a relationship between a slot and an item.. state would be a slot being "equipped/unequipped/injured/amputated"

#

states are typically finite and don't really change over time.. or only marginally so... whereas I see inventory and items as something that will continuously grow

grim oxide
#

The only way the game knows you have something equipped is by it being in that backing field

#

That's a state

#

The item isn't marked on its own object in any way when equipped

#

The item isn't concerned with being equipped or not, rather

grim oxide
#

Oh this is exactly what I need 😛

#

Pointers that aren't gross 😛

#

Wait ...

scenic forge