#archived-code-advanced

1 messages ยท Page 23 of 1

misty glade
#

It's like how when I first started I wrote my own tweening library instead of just using DOTween (or @kindred tusk's)

analog nexus
#

It is an internal r&d project right now

undone coral
#

once you have done

while (hasEvent) {
  var event = events.Next();
  yield return StartCoroutine(DynamicDispatchFor(event))
} 

you've reinvented unirx, even if it looks like you haven't

kindred tusk
#

It's not finished haha

undone coral
misty glade
undone coral
#

lol

kindred tusk
undone coral
#

lol

misty glade
#

OK afk! gotta get back to work .. thank god the India engineers at microsoft are offline, I can't even... parse their english

#

"test out this if the port on that ACI"

undone coral
#

@analog nexus like if you're using a generated c# http client, or something from github

#

is that what the idea is?

#

also if you're targeting android...

analog nexus
undone coral
#

R&D and android don't really go well together

undone coral
#

i am really not trying to shake you down

analog nexus
#

We use plain .net httpclient with all async calls

undone coral
#

it is just funny

#

how much harder you've made this for yourself

#

how your goals are all at odds with each other

undone coral
#

you can use unitask with unitywebrequest, which is a good idea

undone coral
#

like what is the game, generally?

#

like Android and R&D doesn't make sense, and it sounds like you or your team is fairly new to unity

#

which is okay

#

you're here because you want to learn how to do this better

analog nexus
#

We've been doing unity for a couple of years

#

Httpclient had not been an issue

undone coral
#

sometimes i feel like statements like that, while they can be true, are strongly at odds with the other facts

#

do you see what i mean

#

it is definitely a novice thing to do to use httpclient

#

it sort of isn't material whether you or your team have personally be using unity for 2 years

analog nexus
#

The workaround is - hold on - new HttpMethod("PATCH") instead of HttpMethod.Patch

undone coral
#

Httpclient had not been an issue
you are in this discord, right now, discussing how httpclient isn't just an issue, but a particular weird issue

#

do you see what i mean?

#

you're saying R&D, but there is no viable R&D to do on android

#

you're saying no issue, and then there's an issue

#

you're saying 2 years, and you use httpclient

#

i'm really not trying to bully you, just to open you up

analog nexus
#

R&D means research and development and that can target anything really

undone coral
#

you're saying you're not at liberty to discuss somethin,g and of course, you can describe the game in general terms

#

it will help me give you good advice

#

maybe it will only really run on desktops

#

and on windows

#

like i understand it might be aspirational to put something on android

#

on a phone

#

but you guys might not be ready for that

#

maybe it doesn't matter if it's buggy

#

maybe you don't have a deadline, which is a good thing!

analog nexus
#

If you are saying UWR would solve this issue that is a weak argument because it also does not implement PATCH, do you see that

undone coral
#

i asked you early on if you control the source to the http API that uses patch

#

PATCH in general is pretty bad

#

it's hard to say, because you haven't told me what this is

analog nexus
#

If you're saying Android mono does not have httpclient, that would be a very compelling argument

undone coral
#

i am operating in the dark, and you are giving me a hard time for not knowing facts. i have to sus them out of you by being a little mean, which i am sorry for

analog nexus
#

Patch is bad?

undone coral
undone coral
#

if you are using them, you are usually doing something wrong

#

i don't know, i worked in R&D for a while

#

nobody i know who thrived at R&D was ever this disrespectful or difficult

#

is this your goal, to do this well?

#

do you want to make R&D, or do you want to do something else?

#

is it a crypto thing?

#

i can only imagine a few reasons you'd be shy to say what it is

analog nexus
#

You are very confident but have weird opinions about http methods being bad or platforms you admit you know little about the state of the implementation

undone coral
#

listen it's your project

#

you haven't told me what it is yet

kindred tusk
#

What's the question @analog nexus ?

undone coral
#

i think i've helped out as much as i can

kindred tusk
#

I scrolled up but I can't find it

analog nexus
#

It doesn't matter what it is called?

undone coral
#

something something, httpclient.patch doesn't work but new httpmethod("PATCH") does, on android

#

the user found a bug in httpclient on android

#

and is confused why that would be buggy

analog nexus
kindred tusk
#

The user lol

undone coral
#

i said use UnityWebRequest

#

lol

analog nexus
#

And it's not a windows/Mac/Linux thing

#

It works for me on Linux

undone coral
#

the rest of this is the user being kind of stubborn about this. he's welcome to use whatever buggy thing it is

analog nexus
#

Coworker tested on windows, Mac and Linux

undone coral
analog nexus
#

Works for him

kindred tusk
#

Ah interesting. I've always used UWR myself.

#

As horrible as it is

analog nexus
#

I never mentioned Android @undone coral

kindred tusk
#

I reckon you might be able to find a library if you need something nicer

analog nexus
#

We already have a workaround

undone coral
analog nexus
#

I just wonder why it is different between developers

#

Yes

#

It works reasonably well

undone coral
analog nexus
#

Haha

undone coral
#

it will have a lot of bugs and discrepencies

analog nexus
#

Oh go home

#

Laughing out loud

undone coral
#

well that was an interesting journey

#

i do feel the pain for the linux editor users

kindred tusk
#

It's an interesting question @analog nexus. Do you know what the exception is?

analog nexus
#

It's a personal choice but it'll take a lot of bugs for me to go back to windows

kindred tusk
#

Are they on different OS or just different distros?

small latch
analog nexus
#

This one i believe

undone coral
#

i wasn't expecting the linux editor to be the key fact i needed to know

analog nexus
undone coral
#

we can't really rely on his coworkers...

#
        public static System.Net.Http.HttpMethod Patch => throw new PlatformNotSupportedException ();```
i guess this is plain as day
#

i don't know

#

i don't know what this is really about anymore

#

good luck out there

analog nexus
#

Right, so why do I not see this exception

undone coral
#

i think the code is really really buggy

#

and your comprehension about what is going on is limited

#

is my honest answer

#

that is the best explanation

kindred tusk
#

@analog nexus are you building il2cpp?

analog nexus
#

No

kindred tusk
#

I guess that uses the same library

undone coral
#

without the code, or the context of the project, or any substantive facts

#

it's hard to give you a good answer

analog nexus
#

Maybe it is pulling in my dotnet system libs?

undone coral
#

however, the overwhelming preponderance of other facts - the linux editor, the weirdness around telling us what the game is, the multi-platformness, using PATCH - suggests strongly that you guys have made some bad decisions that you can earn a lot from revisiting

undone coral
#

sure

#

this is like the part of the tarot card reading where someone asks "oh, that's what the cards say?"

#

"sure"

analog nexus
#

If it helps you, let's call it super turkey puncher 3

proven phoenix
#

I'm trying to do smth pretty weird, maybe somebody got some input on it.

I have 2 canvases, both have the same setup. (pixel ratio, canvas scaler,...)

1 canvas contains ui objects, usually nested. for example an inventory parent with items nested (its obviously more complicated but for the example keep it simple)

now, i have an image on the other canvas.

I am trying to move the image on the other canvas to overlay a child element (for example an inventory item) of the other canvas.

#

anybody got an idea how to do that and which coordinates to use

abstract folio
compact ingot
proven phoenix
#

cause i am adding gamepad support as an afterthought and i want to add a virtual cursor that works for my menus. my menus are split up in different canvases and i just try to use it as a visual indicator

#

its not really about why, its more about how

compact ingot
proven phoenix
#

ok but i know my shit

compact ingot
#

in any case, you'd use screen space coordinates obviously

abstract folio
proven phoenix
#

so can i just convert world space (transform.pos) to screen space

compact ingot
#

yes

proven phoenix
#

and then the other way around i guess

compact ingot
#

yes

abstract folio
#

that particular class is for RectTransforms.. which is what ya use on canvases, but yeh

proven phoenix
compact ingot
#

assuming you are using an overlay canvas btw

#

otherwise you'd just use the RectUtility and use the canvas coordinate system

abstract folio
#

Can someone please confirm this: When in a coroutine, and I call another function of the same type e.g.
IEnumerator MyMainCoroutine() { yield return MySubCoroutine(); DoStuff(); } IEnumerator MySubCoroutine() { if (someCondition) yield return 1; }

Would it be accurate to say that MyMainCoroutine will relinquish control to the main thread, before calling DoStuff(), if, and only if, someCondition is true?

compact ingot
#

yes

abstract folio
# compact ingot ~~yes~~

indeed- that will always happen.. just need to know if control will go back to the main thread when MySubCoroutine calls yield return 1 , and WONT go back, when it doesn't.

compact ingot
abstract folio
#

k, I shall try and test

abstract folio
abstract folio
#

dang now I have no ideas on how to get around that, without, obviously, having the conditional in the main function.

drowsy estuary
#

How do I define a LayerMask that is all layers excluding one?
My first though was to do this:
LayerMask all = ~0;
LayerMask layerToIgnore = 4;
LayerMask allExceptLayer4 = all & ~(1 << layerToIgnore);
But when using this LayerMask to raycast against all layers except "layer 4", it does not seem to work.
Am i misunderstanding how the "mask" part of LayerMasks are supposed to be used?

compact ingot
#
LayerMask all = ~0;
LayerMask layerToIgnore = 4;
LayerMask allExceptLayer4 = all ^ (1 << layerToIgnore);
drowsy estuary
#

oh lol maybe I misremembered how to do bit exclusion

#

hang on

undone coral
#

yield return 1 will have the effect of resuming the coroutine's execution when that script's Update will be called next

#

does that make sense?

drowsy estuary
undone coral
#

@abstract folio that is almost exactly how it actually works. Update will not appear in the stack

#

oh never mind

abstract folio
undone coral
#

it's hard to translate into updateloopese

abstract folio
#

@undone coral I'm definately thinking about "rolling my own", with update- that might just be the workaround I need

undone coral
#

don't do that

#

you don't need update

#

what do you think you need to do that?

#

i actually wrote a wrong translation, that's why i deleted it

#

it is very hard to write what you did in updateloopese

#

translating from coroutines (good) to updateloopese (bad)

abstract folio
#

I have a function I'd like to call that basically yields the coroutine, but does so on some condition I compute. if the condition is false- I want the routine to continue processing this "frame". let me put up the code one mo

undone coral
undone coral
# abstract folio I have a function I'd like to call that basically yields the coroutine, but does...

okay well that's a well known wart of coroutines. the workaround is documented here: https://forum.unity.com/threads/yielding-a-nested-ienumerator-waits-a-frame-even-on-break.772352/

#

basically you do

abstract folio
#

nice, gonna check that out- thx

undone coral
#
// type is IEnumerator
var childCoroutine = MySubCoroutine();
while (childCoroutine.MoveNext()) {
 yield return childCoroutine.Current;
}
undone coral
abstract folio
#

perfect

undone coral
analog nexus
# undone coral i can only imagine a few reasons you'd be shy to say what it is

weird http methods are bad, yes
the method is literally just a string in the header of the http request. nothing special about what it is except frameworks like to introduce enums for well known ones
if you are using them, you are usually doing something wrong
strong disagree, that is your opinion
nobody i know who thrived at R&D was ever this disrespectful or difficult
not sharing your opinion is not disrespectful. if you have good arguments they can stand on their own merit and not "do it my way because I told you so and because people gestures vaguely say so

is it a crypto thing?
it has nothing to do with what the original question or the issue you try to make it so hard is. The only reason why you're so hard headed about knowing what the project is called or what the intended use case is to dis the project as a whole.
i can only imagine a few reasons you'd be shy to say what it is
dito

fresh salmon
#

Oh that's typical Pangloss banter

#

You can just ignore when it gets too wild

#

They do this all the time

analog nexus
#

you made your point "UWR is supported by unity" well enough. but I dod not ask for your opinion on system.net.httpclient vs UWR

#

mixing in "well you and your team are probably unity noobs that got their programming from youtube to do a crypto project" is just ๐Ÿง‘โ€๐Ÿณ ๐Ÿ‘Œ

#

ugh. I grew up on IRC. you'd expect people to grow up

indigo citrus
#

What am I doing wrong here?
2022/10/18 19:41:16.318 14236 14286 Error Unity [Authentication]: Request failed: 401, {"title":"PERMISSION_DENIED","detail":"unable to validate token","details":[],"status":401}

#

Trying to SignIn with google play games

#
PlayGamesPlatform.Instance.Authenticate(success => {
            if (success == SignInStatus.Success) {
                Debug.Log("Play Games Services Authentication successful");
                string userInfo = "Username: " + Social.localUser.userName +
                    "\nUser ID: " + Social.localUser.id +
                    "\nIsUnderage: " + Social.localUser.underage;
                PlayGamesPlatform.Instance.RequestServerSideAccess(true, code => {
                    Debug.Log("Authorization code: " + code);
                    token = code;
                    UnityAuthenticate();
                });
                Debug.Log(userInfo);
                PlayerPrefs.SetInt("playgames", 1);
            } else {
                Debug.Log("Play Games Services Authentication failed");
                PlayerPrefs.SetInt("playgames", 0);
            }
            loading.SetActive(false);
        });```
#
private async void UnityAuthenticate() {
        if (AuthenticationService.Instance.SessionTokenExists) {
            /*
            * SIGN IN WITH CACHE
            */
             try {
                await AuthenticationService.Instance.SignInAnonymouslyAsync();
                Debug.Log("Sign in anonymously succeeded!");

                Debug.Log($"PlayerID: {AuthenticationService.Instance.PlayerId}");   
            } catches {}
        } else {
            if(PlayerPrefs.GetInt("playgames") == 1) {
                /*
                * SIGN IN USING GOOGLE PLAY GAMES
                */
                try {
                    await AuthenticationService.Instance.SignInWithGooglePlayGamesAsync(token);
                    Debug.Log("SignIn is successful."); 
                } catch (AuthenticationException ex) {
                    Debug.LogException(ex);
                } catch (RequestFailedException ex) {
                    Debug.LogException(ex);
                }
            } else {
                /*
                * SIGN IN ANONYMOUSLY
                */
                try {
                    await AuthenticationService.Instance.SignInAnonymouslyAsync();
                    Debug.Log("SignIn is successful."); 
                } catch (AuthenticationException ex) {
                    Debug.LogException(ex);
                } catch (RequestFailedException ex) {
                    Debug.LogException(ex);
                }
            }
        }
    }```
#

Do I need to add any url to the authorised list in google cloud?

undone coral
#

this isn't from the documentation

#

it is telling you what the issue is. you are trying to use a server side token from the client.

#

also, your code has invalid syntax - } catches {} - so this is not what you are running

#

what are you actually trying to do?

indigo citrus
#

Well the catches is so it all fits in the message

indigo citrus
#

Also it does get the code correctly

#

The problem is using it

#

I am trying to pass the token to Unity Authenticate so it authenticates correctly with Google Play Games in Unity Authentication

undone coral
#

i think you should probably follow the documentation exactly

#

there is a lot of noise, and i can tell you want something that "just" works

#

did you find examples doing what you want?

indigo citrus
#

Yes

#

And I used them ig

#

Also I think I did follow the documentation

#

The entire code is basically code from documentation but with some ifs and elses

undone coral
#

hmm

#

can you show me that documentation?

#

i don't see where you read token here i found it

#

honestly this is a huge mess

#

it is impossible to see what is going on, where token is being used, etc.

#

because it's not in this code snippet @indigo citrus

indigo citrus
#

I can send the whole class if needed ig but Ill explain a little bit more

#

And maybe just go to the part thats throwing the issue

#

You can ignore everything but the sign in using google play games if Im correct

undone coral
#

here is a translation of what your code is trying to do, but actually makes sense.

// install UniTask from https://github.com/Cysharp/UniTask 
using UniTask;

void Start() {
 AuthenticateWithGooglePlay().Forget();
}

async UniTask AuthenticateWithGooglePlay() {
 var pgpAuthenticateFut = new UniTaskCompletionSource<SignInStatus>();
 PlayGamesPlatform.Instance.Authenticate(pgpAuthenticateFut.TrySetResult);
 var success = await pgpAuthenticateFut.Task;

 if (success != SignInStatus.Success) {
  Debug.Log("Play Games Services Authentication failed");
  return;
 }

 var pgpSsaFut = new UniTaskCompletionSource<string>();
 PlayGamesPlatform.Instance.RequestServerSideAccess(true, pgpSsaFut.TrySetResult);
 var code = await pgpSsaFut.Task;

 await AuthenticationService.Instance.SignInWithGooglePlayGamesAsync(code);
}
indigo citrus
#

Where it does use the token in the method SignInWithGooglePlayGamesAsync

undone coral
#

@indigo citrus does this make more sense?

indigo citrus
#

I mean yeah but thats what its basically doing ;-

undone coral
#

don't do it the way you're doing because it's completely incomprehensible

indigo citrus
#

But it has the mess of checking if a user is already cached

undone coral
#

so it's impossible to know if there's some bug

#

well you can do it much easier here

#

the thing about a user being cached isn't related to your error

#

in my experience when i see code that is totally bonkers, rewriting it all is the best approach

indigo citrus
#

And if cant for some reason login to google play games it will just go with a anonymous user

undone coral
#

you haven't sent me a link to the docs you used yet

indigo citrus
#

Oh wait 1 sec

undone coral
#

you can write that later

#

it is really easy to do that in the snippet i wrote

#

as opposed to the one you have

#

which is "callback hell"

indigo citrus
#

And the all the docs pages related to it

#

And signing in a cache user and signing in a anonymous user

undone coral
#

okay, based on what i see there

#

it's probably because your code is nuts

#

try mine

#

install unitask

#

you can't use regular unity async anyway

indigo citrus
#

Ill try later and see how it goes I guess thank you

#

I am in my phone rn xD

#

I will check everything you sent

#

In order to accomplish what I need

#

But I am in my phone so theres nothing I can do rn will make sure to give you feedback after doing so ๐Ÿ™‚

undone coral
#

understandable lol

#

i've had bad luck helping people today

indigo citrus
#

xD keep the good work ๐Ÿ™‚

undone coral
lyric dragon
#

Hello guys, I am developing an Android application and I am trying to test my android library (written in Java) in Unity, but seems like debugging does work differently (I can't just enter the game mode and see the log of my library, since Application is in Editor mode, not in Android device)

How to debug such programs?

regal lava
#

yeah, I'd like to know some options for that, otherwise I guess I'm emulating the devices

sly grove
#

second, you can install Android studio and attach the debugger from there and debug your Java code.

#

Android Studio also has Logcat built in

sullen dock
#

hello, I want to write a Hexagonal Grid Library for my game. I guess I have to take out the "monobehaviour" word so I can use it outside of an scene. Then I though about using static methods for the library like public float GetHexagonWidth(Hexagon h) but then I realized all hexagons will have the same width, so I wanted to store it in some place rather than storing it in every hexagon, or calculating it everytime I want to use it. Is there a way to handle my problem?

sly grove
#

There's a Grid component, built into Unity that can handle hexes out of the box.

sullen dock
#

thank youi

sullen dock
stuck onyx
#

sorry guys but i dont know where else ask this... how do you say in technical english when you debug in device instead of normal debug in editor?

#

does it have a name or simply.... "debug on device" ?

#

im talking abut debugging with the IDE obviously (VStudio or Rider....)

flint sage
#

Debug on device is pretty common

#

Or build

stuck onyx
#

and what do they mean when they say.... "standalone debug" ?

#

or standalone build ?

stuck onyx
flint sage
stuck onyx
#

i've read it around a few times but if debug or build on device is the most common its fine, thanks a lot

flint sage
#

But probably not waht they mean

stuck onyx
#

Rider has a bug that doesnt allow to debug

#

you connect the device and stops at the first breakpoint but after that it hangs

#

and VS simply doesnt connect to the device

#

it sucks

flint sage
#

That might be on Unity instead ๐Ÿ˜›

stuck onyx
#

yeah you might be right, still they have it in their issue tracker (rider)

flint sage
#

I know in some versions you can't profile on android because unity messed up

#

So wouldn't surprise me if they did the same for dbeugging

stuck onyx
#

ill check the forums

regal olive
#

Problem: CreatePrimitive(), new GameObject() and Instantiate() fail when called in large numbers during update
Hello everyone, I have come across a problem yesterday afternoon that to this day I have no idea at all how to solve. Let me start by showing you a video.

#

I am preparing some code for a voxel engine I'm making, and here is a prototype of a chunk generator. As of now, this is just a script that generates cubes in a set grid around a focus point, which in the hierarchy is denoted as "focus".

#

Everything the script ought to do as of now is to simply delete cubes that are too far away from the focus, and generate new ones in valid but empty places.

#

The way I have decided to implement this is as follows:

  1. Let there be a three-dimensional array, chunkGrid, of class ChunkPlace, the latter storing information about chunks, such as LOD stage, the mesh/object, and the chunk as a node for an Octree (sort of).
  2. chunkGrid does not have an instance of ChunkPlace at every position. Only positions that are inside the circle are not null.
  3. We will use chunkGrid primarily to calculate the world position of the chunks through the array position and some other data.

Now, here is the algorithm that is run every update for every array entry in chunkGrid:

  1. Is the entry null, i.e. is not it part of the sphere? If so, skip this entry.
  2. Is the entry's node field null, i.e. is the place inside of the sphere, but isn't occupied by a chunk? If so, generate a chunk and place it in.
  3. Is the entry's chunk too far away from focus? If so, remove the chunk (this will never fire simultaneously with the before mentioned point, as it will never generate chunks outside of reach.)
#

Here is the relevant code:

#
private void ConstructChunks() {
//We don't start at 0, but at negative extent. Ix, iy and iz will convert this to an index that starts at 0
//and ends at 2*radiusInChunks-1, which are also the bounds of the array.
  for (int y = -radiusInChunks; y < radiusInChunks; y++) {
    int iy = radiusInChunks + y;
    for (int x = -radiusInChunks; x < radiusInChunks; x++) {
      int ix = radiusInChunks + x;
      for (int z = -radiusInChunks; z < radiusInChunks; z++) {
        int iz = radiusInChunks + z;
        if (chunkGrid[ix, iy, iz] != null) {

          //create a chunk if a place is expected but empty
          if (chunkGrid[ix, iy, iz].chunkNode == null) {
            Vector3 playerPos = player.transform.position;
            VoxelOctreeNode chunk = new VoxelOctreeNode();
            chunkGrid[ix, iy, iz].obj = ConstructOctreeNodes(chunk,
                                                             chunkGrid[ix, iy, iz].LODStage,
                                                             Vector3.zero,
                                                             snapToStep(new Vector3(x*chunkExtent*2+playerPos.x,    
                                                                                    y*chunkExtent*2+playerPos.y,
                                                                                    z*chunkExtent*2+playerPos.z),
                                                                        chunkExtent*2),
                                                             chunkExtent);
            chunkGrid[ix, iy, iz].chunkNode = chunk;
           }

           //remove chunk if it is too far from player
           if (Vector3.Distance(chunkGrid[ix, iy, iz].obj.transform.position, player.transform.position) > loadedTreeExtent) {
              Destroy(chunkGrid[ix, iy, iz].obj);
              chunkGrid[ix, iy, iz].obj = null;
              chunkGrid[ix, iy, iz].chunkNode = null;
           }
          }
        }
       } 
      }
    }
#

Before I continue, I need to mention that the lower bit of the function (the one responsible for removing chunks) is working as intended, so there is nothing to check there.

#

The upper bit, the creation (which is the one we're having a problem with), calls a function that is originally intended to also execute some Octree logic, which right now is disabled, however. You can ignore it and see it as a call to the following logic, which is also the only logic that is executed before the method jumps out:

        GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
        obj.transform.SetParent(GameObject.Find((currlevel+1).ToString()).transform, true);
        obj.transform.localScale = 2 * chunkExtent;
        obj.transform.position = snapToStep(new Vector3(x*chunkExtent*2+playerPos.x,
                                                        y*chunkExtent*2+playerPos.y,
                                                        z*chunkExtent*2+playerPos.z), chunkExtent*2);

The three next lines work as intended. snapToStep() is a function I made to snap the Vector3 to a grid which is formed by a certain step, in our case double of chunkExtent.

#

However, as we see, for some reason the first line (and the next ones) aren't even called at times.

#

In the video, you saw small gray gizmo circles. They are drawn here:

void OnDrawGizmos() {
        for(int y=-radiusInChunks; y<radiusInChunks; y++) {
            for(int x=-radiusInChunks; x<radiusInChunks; x++) {
                for (int z=-radiusInChunks; z<radiusInChunks; z++) {
                    if(chunkGrid[radiusInChunks + x, radiusInChunks + y, radiusInChunks + z] != null) {
                        Vector3 playerPos = player.transform.position;
                        Gizmos.DrawSphere(snapToStep(new Vector3(x*chunkExtent*2+playerPos.x,
                                                                 y*chunkExtent*2+playerPos.y,
                                                                 z*chunkExtent*2+playerPos.z), chunkExtent*2), 0.33f);
                    } 
                }
            }
        }
    }
#

These circles are there to signify that the traversal of the array and the conditional clauses are executed correctly, as we see the gray gizmo circles exactly where we would expect a chunk to be generated.

#

Hence, this part of the logic can't be wrong (neither the traversal of the array, nor the first condition)

#

Suspect: I honestly believe this isn't an error on my part. All the code is correct, especially reinforced by the gizmos. I also revised it with a relative, who has >20 years of experience with programming - he couldn't find the issue either. Could it be that for some reason the Update() execution just breaks out after a certain amount of iterations? Notice in the video how, of the chunks that are supposed to be loaded, only the outside chunks are loaded, not the inner ones.

#

The pattern of the faulty generation also makes me believe Unity interrupts the loop at some point for some reason.

#

Or, maybe some exception is thrown, but isn't notified in the log?

#

Fyi, yes, the log is absolutely clean.

#

Thing's I've tried already:
-Swap out CreatePrimitive() with new GameObject() and manually adding components per script
-Change the initial condition from checking if the ChunkPlace entry in chunkGrids is null, to simply checking manually if the chunk is inside/outside a sphere.
-Putting the entire logic in OnDrawGizmos(), out of suspicion of Update() especially failing, while the gizmos work with the iterations.
-Adding private fields of types MeshRenderer, MeshFilter and BoxCollider at the top of the script, as I've heard that Unity might throw these APIs, which are needed for CreatePrimitive(), away if they are not used anywhere
-Swapping out the code so that it first tries to delete, then generate. This actually made things worse.

sweet niche
regal olive
#

Yes, because chunkGrid does not store chunks, but objects of class ChunkPlace, which is a placeholder for every information about a chunk.

#

Its presence doesn't signify a chunk, but a valid place for a chunk. We don't want that to change ^^

sweet niche
#

ah i get it sorry

regal olive
#

I have tried swapping that condition for a simple sphere check (specifically if(x*x+y*y+z*z <= radiusInChunks*radiusInChunks), no change.)

sweet niche
#

the indentation on discord is shit

regal olive
#

It is..

sweet niche
#

really dumb check but you tried to find out using debug.log how far along it goes?

regal olive
#

I would try, but the amount of chunks that are generated is so much that it becomes hard to debug using Debug.Log.. ^^'

#

I could try lowering the radius drastically and see where it goes, though.

sweet niche
#

OnDrawGizmos you only check if the chunkGrid Element is not null

#

check if the node is null also

#

chunkNode

regal olive
#

Hm, alright!

sweet niche
#

increase the distance and see if thats the issue

lime plover
#

Hey can someone please help me out with some mathematics and astronomy? In short, I'm making a realistic game based on the island Tetepare, and I want the path of the sun (yes, I know the Earth rotates around the sun not vice versa, but in videogames the sun rotates around the Earth) to be as accurate as possible. I found this website that lets you see the exact position and rotation of the sun at any date and time https://drajmarsh.bitbucket.io/sunpath3d.html . I want to implement this into my game though I'm not sure how. I don't know what formulas are being used here, and what the best way would be to implement this. Any help is appreciated ๐Ÿ™‚

regal olive
#

Another thing I've found out that as long as the focus is at (0, 0, 0), chunks are generated once and done, which is what we want. We don't want them deleted and re-generated every frame. However, even if just a teeny tiny bit, if the focus is moved in any direction, well...

#

The log says it constantly generates them infinitely many times. In the inspector I can see a finite amount of cubes, however - for some reason, it generates cubes, which it instantly removes afterwards.

#

Hm, maybe those are the cubes that are missing?

#

In that case, the removal function could have a wrong condition.

sweet niche
#

The radiusInChunks might not match the actualy distance for the loadedTreeExtent

regal olive
#

It doesn't, but those are two seperate things.
loadedTreeExtent is the world radius of the sphere in which chunks should be loaded. It is defined as chunkExtent*2 * radiusInChunks.
radiusInChunks is the radius of the sphere measured in chunks.
chunkExtent is the extent of a chunk from its center to its surface, aka 2*chunkExtent is the width of a chunk.

#

chunkGrid uses radiusInChunks because it is independent of the size of chunks - it is merely an abstraction of the chunk sphere around the player.

#

loadedTreeExtent is used only for the Vector3.Distance() function, in which we expect world values.

#

But!

#

It is indeed true that for all other functions we use our own equation to find out of it's inside the sphere, while here we use Vector3.Distance(). Let me try to change that and see what happens

#

Wait, I think I'm onto something..

#

Nope, I'm not.

#

However, on second inspection, the issue is indeed with the removal condition. The log shows it's hectically creating and removing chunks every frame, even though focus stays still.

regal olive
#

Oh my, I think I know why.

#

You see, chunkGrid is fully abstracted. That means it doesn't take into account anything in the world, it only sees a static grid of cubes arranged in a sphere.

#

That also means however, that if we move the focus forwards, the sphere function calculates that new chunks should be placed at the new front

#

however, for chunkGrid, there is no "new" front, as it never listened to focus anyways. It is an abstraction

#

And since the chunks one position behind the front (which, for chunkGrid, is still the front) still exist, chunkGrid never released their position, and as such, no new frontal chunks are generated.

#

I should just generate a grid-snapped sphere of chunks around the focus like a normal person instead of relying on weird arrays such as these...

#

Off to the Unity forums I go. @sweet niche Thank you for your help, though. ^^

sweet niche
#

Would it not be better to generate the whole map. Then focus would only turn on the renderer for the cubes near it

regal olive
#

Well, it is a procedural voxel engine.

#

The "whole map" could require terrabytes of memory if loaded at once - remember that right now we're only dealing with chunks, later on each chunk will have an Octree structure beneath it of several levels ^^

#

With each Octree node taking up ~26 bytes (that's the best I could do), and every level being 8/9% more memory than the previous, assuming a depth of 5, every single chunk could take up to ~832 kilobytes

#

Well, that is assuming that every node is in full resolution, which it certainly won't be. I could guess that ~30% of nodes would be in full resolution

#

Let us take a guess of ~100 kilobytes of memory for each chunk. For a render distance of 32 chunks in each direction, we could expect already some 2 GB to be gone just for the voxel engine

#

And this is just talking about memory, not even rendering

#

But I will add in certain optimisations (such as LOD) that will certainly let you have a larger render distance than 32 chunks, and more resolute chunks to allow you depths of even 8 maybe. Yet even then, we won't be able to load in the whole world ๐Ÿ˜…

mint sleet
#
{
  "data": {
    "id": 3,
    "userId": "1960a78f-4d21-4e2e-a81d-f75a8e55da30",
    "creationDateTime": "2022-10-18T13:51:45",
    "updateDateTime": "2022-10-18T15:50:11.003",
    "settings": "{"selam": "ahmet"}",
    "version": "1",
    "courseId": null
  },
  "success": true,
  "message": null
}```
#

Hello I want to remove the quote of the settings

#

because of those quotes the string did get parsed by JSON parser

#

how can I remove them?

compact ingot
mint sleet
#

the settings field is stored as a string value in the database. I do serialization twice.

#

But I solved it anyway in a not elegant way (string parsing.)

#

Tahks

mint sleet
#
        public async Task MakeRequest<TRequest, TResponse>(VRCloudRequestBase vrCloudrequest, [CanBeNull] Button clickedButton, [CanBeNull] UnityEvent<VRCloudResponseBase> callbackFromSignature)
#

What about here? when I call this function, I have to sign the callback as null in the caller method

#

I want let people decide whether they write a callback or not. I do not want them to explicitly write "null" in the caller function

#

how can I do that without overload methods.

sly grove
#

although UnityEvent is kind of a weird way to handle callbacks

mint sleet
#

I made overload it worked. will take a look into default also.

#

I made an interesting logic. People are surprised ๐Ÿ™‚

#

@sly grove

sly grove
#

default parameters are basically just syntax sugar around overloads

dapper cave
#

what even method gets called before unloading domain that happens before recompiling?

#

or callback

inner juniper
#

Hello! I have generated a file that I want to save in a directory inside my computer. Everything I find online is related to online stuff, but this is local. How do I go about this?

plain abyss
#

If I have a non-regular polygon defined by a list of vertex locations defining the perimeter of the shape, how would I go about turning that into a mesh face? How would I know which vertices to combine into a triangle? I'm assuming there's some sort of algorithm for this but I'm not sure what to look up

plain abyss
stone crag
#

hi, is there any way to use the "get spectrum data" but with the computer sound like if i put a video on youtube it detects it?

vivid talon
#

Hello

stone crag
#

still writing?!

vivid talon
#

I have a thread running System.Net.Socket.UdpClient.Receive()
When I send messages from my computer, the unity instance running that thread receives the message
When I send from another computer the message is not received
If I try to run that same code in a netFramework 4.7.1 console application the message is received corretcly either if I send from another computer or locally from my computer

#

what is going on with unity?

#
 public void StartListener()
        {
            UdpClient listener = new UdpClient(_configuration.UDPPort);
            IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, _configuration.UDPPort);

            try
            {
                while (run)
                {
                    byte[] bytes = listener.Receive(ref groupEP);
                    string input = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                    Debug.Log("got "+ input);
                    DataStructure.inbound.Enqueue(input);

                }
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            finally
            {

                Debug.LogWarning("=========== Listener Socket closed! ==========");
                listener.Close();

            }
            
        }
#
        private Thread InstanceCaller;
        private void Awake()
        {
        InstanceCaller = new Thread(
                new ThreadStart(listener.StartListener));
            
            InstanceCaller.Start();
}
#

Does anyone have any idea what is going on?

lime plover
#

I'm running the InputActionTrace example code and I get a memory leak even after disposing, anyone know how to fix this?

#

Here's the error log

young wraith
#

Hi good day I'm trying to convert Setpixel to SetPixel32

#

above is my setpixel code

#

and this is what I did

#

But it's not working

brisk pasture
#

you should explain whats not working

#

also there is a implict cast

#

Color32 color = new Color(0.5f, 1f, 0.5f, 1f); for example works

young wraith
#

@brisk pasture sorry the dirtMaskArr[arrElement] = new Color32(0, Convert.ToByte(a), 0, 255); part is not working

brisk pasture
#

so what type is a

#

and what range is it in

young wraith
#

a is byte

#

range from 0 - 255

brisk pasture
#

why are you converting a byte to a byte then

young wraith
#

double a = (pixelDirtMaskA * pixelDirtA) * 255;

#

then I converted it to byte

brisk pasture
#

would just confirm you are in the right range before converting

young wraith
young wraith
#

yes its right range 0-255

lament salmon
young wraith
#

SetPixels32(int x, int y, int blockWidth, int blockHeight, Color32[] colors, int miplevel = 0);
I dont understant the blockWidht, blockHeight, Color32[] colors part

#

if you compare it to setpixel
public void SetPixel(int x, int y, Color color, int mipLevel = 0);

rugged radish
#

it sets a subregion of pixels inside a texture

#

the other one sets just one pixel

proven venture
#

and one takes a color32 while one takes a color

lyric dragon
#

Anyone has experience in using native Android libraries for their projects?
I am trying to write my own library and use it in my unity app, however I can't find a way to provide a context to my application.

I checked the resources in the internet and they use AndroidJavaClass "com.unity3d.player.UnityPlayer", then make a static function call to currentActivity; my problem is that I get the error saying "java.lang.NoSuchMethodError: no static method with name='currentActivity'"

anybody has any idea what to do?

lime socket
#

Does anyone have experience of making NFT games? In my case, I just wanna import some random 3D NFT into my project, and I have no idea how do I have to do it

long ivy
lime socket
long ivy
#

from where, out of what format? What have you tried? a few seconds of searching says maybe they are GLB/glTF, so you need to parse that format at runtime and create a mesh from the geometry inside

lime socket
# long ivy from where, out of what format? What have you tried? a few seconds of searching ...

from where - idk, some open sources like opensea
out of what format? - doesn't even matter, just wanna do it, as a mesh or as a gameobject
what have you tried? - the only thing I tried is to import some 2d NFTs firstly, and generally, it worked, but I have no goddamn clue how to do it with 3D ones

if you think that I do know at least smth about NFTs, you are wrong, I have no idea about blockchain technologies, although I'm working with Unity since 2019

#

Is there any, like, tutorial, guide, etc of doing that on the Internet?

long ivy
#

if you haven't got a clue what the input is, you have no chance of solving this. Start by figuring out what exactly you're trying to import, and then you'll be able to figure out the rest

lime socket
#

ok, so for example I'm trying to import 3d NFT model, .gltf, during the runtime, how do i?

long ivy
#

I'd start by typing Unity3d import gltf runtime into google and seeing if you can get any of those solutions to work

young wraith
rugged radish
#

blockWidth and blockHeight are the height and width of the subregion inside the texture you're changing, with x and y pointing to the origin of the subregion
so, if you want to change a 100x100 texture's center 50x50 subregion, use x = 24, y = 24, blockWidth = 50, blockHeight = 50

and if you want to set the entire texture, just use this overload public void SetPixels32(Color32[] colors, int miplevel = 0); instead

kindred night
#

Has anyone ever made a RayMarching script for their games? If yes, could you give this friend a hand? ๐Ÿ˜ญ

young wraith
#

so if I have blockWidth = 50, blockHeight = 50 I should have 2,500 elements in Color32[]

rugged radish
#

that's correct

plain abyss
crimson ruin
#

Is there any way to uniquely identify a StateMachineBehaviour which is persistent across runs? It seems impossible to get the state information from within a StateMachineBehaviour, and the only solution I've found is naive & depends on the fact that the StateMachineBehaviour has been entered at least once

thorny lion
#

how can I attach a reorderableList to a unity editor window?

flint sage
#

Use either a IMGUIContainer or use the ListView control

thorny lion
#

yes ListView made the work

split sierra
#

Hey, I have a problem. I have a Gameobject with a list of weapons(custom class) and in this class there is a Gameobject variable called bulletPrefab and on this bulletPrefab is a script with some public variables like damage and so on. I now want to be able to change the variables on the prefab from script. Hope someone knows what i mean and can help me (:

flint sage
#

Keep in mind you have to cache it and dispose it, so you can't just create it each frame

thorny lion
#

or you can do a stupid but workable

someGameObject.GetComponent<SomeScriptOnIt>().SomeProperty = "SomeValue";
#

It there a way to make it shorter?

split sierra
#

My Gameobject with the avalible weapons script on it Instantiates bullets like so

Instantiate(avalibleWeapons[selectedWeapon].bulletPrefab_, gunTransform.position, Quaternion.identity);

And i want to be able to change the properties of this bullets like damage speed etc from script, so that all the Instantiated bullets have values i choose in script
Currently i modify the values like this:

Weapon w = new Weapon...
w.bulletPrefab_.GetComponent<Bullet>().effectDamage = w.damage_;
w.bulletPrefab_.GetComponent<Bullet>().effectDuration = w.effectDuration_;

hope you understand what i mean

thorny lion
#

so what's the problem

#

do you want to optimise it?

#

shorten the code something?

crimson ruin
#

You can sacrifice performance by decoupling it via SendMessage, BroadcastMessage if that's your issue

split sierra
#

no the problem is that it is not working the newly created bullets all have the same values no matter what i change it to

crimson ruin
#

From your code it looks like you're modifying the prefab instead of the instance

#

var go = Instantiate(avalibleWeapons[selectedWeapon].bulletPrefab_, gunTransform.position, Quaternion.identity);

#

And then do GetComponent<> on go instead

split sierra
#

Yes I did it like this but it seems like a bit of a workaround no?
because like this i have to set it new for every bullet i Instantiate and I just wanted to know if it is possible to set it for the prefab attached so it automatically spawns all bullets with the right values

sly grove
#

If you want different values you should do one of two thigns:

  • switch to a different prefab that has the different values
  • Use a pattern where you use the prefab as a base, then apply some transformation/augmentation on the values after spawning the new bullet.
verbal hare
#

How does Unity detect when a NativeCollection is disposed or not?
A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details.
I am disposing my NativeArrays eventually so I am not sure how Unity is determining that I am leaking them.

undone coral
#

you should use a persistent allocator if you want bonafide manual memory management

#

everything else is a combination of some nuanced heuristics and the consequence of the C# object being finalized

undone coral
#

there's no meaningful difference between a prefab and a copy of it that was never active once (i.e. Awake was never called)

verbal hare
undone coral
undone coral
#

do you see it when you unclick play in the editor?

verbal hare
#

Seems to happen when editor is not focused, or when I return from editor. I create the NativeArray during ScriptableRenderPass.OnCameraSetup and dispose it during the next beginframe callback. I suspect that a delay between the end of the frame and the start of the next one due to the editor becoming inactive might cause Unity to misidentify the leak

undone coral
#

in this case, when you see that message, the number of references to the C# NativeArray object goes to zero, and you personally did not call dispose, so it is considered a leak

undone coral
#

but it might not matter because it is in the editor

#

it's possible to not render the next frame

#

this makes sense to me

#

so it's a real leak

verbal hare
#

I also dispose on the ScriptableRenderPass.Dispose

undone coral
#

you can use the tempallocator instead, which will last for 4 frames by default.

#

the leak is real

#

what is your objective?

verbal hare
#

pass some data to a native render plugin, there the dispatch is asynchronous so I can't simply dispose right after the call

#

I add the NativeArray to a List<IDiposable> could the boxing/lack of type information cause an issue?

undone coral
#

...no, the issue is the leak is real

#

do you understand that the leak is real?

verbal hare
#

lol

undone coral
#

i don't see your code, but the message it is saying about there being a leak is true

#

what you have told me so far makes it sound like the leak is real

#

because the c# object gets finalized before you called dispose, and you chose persistent allocation

verbal hare
#

I will add a finalizer to my object that tracks the arrays and see what is happening there

undone coral
#

that isn't necessarily why it's being finalized

#

the nativearray is being finalized

#

there is... probably a bug in your code. it could be that you have two instances of a nativearray somewhere, by accident, or whatever.

#

you haven't shown any of it yet

#

you haven't really explained what you are trying to do - what does the render plugin do?

#

what you are doing doesn't really make sense yet

#

i guess if you think the leak isn't real, well i can't help you sorry

#

i don't know then

verbal hare
#

there's a bit going on here, I am trying to explain without going too deep into the weeds

undone coral
#

i sent them a bugfix for this

undone coral
verbal hare
undone coral
#

but i need you to say

#

"the leak is real"

#

your understanding of that lifecycle may be correct, but there might also be a bug

verbal hare
#

I'm gonna prove it first, and then I will

undone coral
#

do you agree that is the most likely possibility? that the lifecycle isn't as important as your own code

undone coral
verbal hare
#

I just need to wait for the error condition to occur and see that the finalizer happens without dispose being called

#

I don't think that's going to waste too much time

undone coral
#

honestly

#

i'm not even sure

#

that's really how it works

#

i THINK that's how it works

#

i know that when it says there's a leak, it's real

#

because it's bulletproof

#

it is so easy to implement that kind of detection

#

i am pretty sure that you have to call dispose on your own persistent allocated things

#

but i'm not sure

#

that seems unnecessarily clunky

#

because i haven't used nativecollections to author my own thing. if you told me what you were trying to do, maybe there would be an easier approach

#

instead you're talking about a bug in your code which i can't see so i have no idea, i can't provide any insights

#

there's no std::move in native collections, they are not smart pointers, that should illuminate how their implementation works, and why i believe that you have to call Dispose on your own persistent nativearray, even if it could call dispose in its own finalizer, because it assumes you are using the native pointer elsewhere. but i am not sure about that

verbal hare
#

Sorry, when I was talking about dispose and finalizers, i was talking about my own custom class that manages the native arrays

#

ok, the leak is real

#

the problem is that ScriptableRendererFeature::Create() is called more than once, which is where I allocate the object that tracks the native arrays

thorny lion
#

I am creating custom unity editor using UnityEditor.UIElements. I have a class with public fields that are obviously serialised. Is it possible to get a list of serialised properties of a class somehow? Just like a normal inspector does when you create public fields in a class?

#

I mean do you know how inspector draws serialised fields? I want the same thing

thorny lion
#

I made it. It's csharp functionality here

lime plover
light creek
fresh salmon
#

Static constructor would be the static KinectSensor() method

#

Please use a paste site to post code this big

light creek
#

The only constructor I found is this

fresh salmon
#

Yeah the error reports a static constructor but your decompiler might just be stripping it out for clarity

light creek
#

I just used a different decompiler and it found it

fresh salmon
#

Open it

light creek
#
        void  .cctor() cil managed
{
  // Code size       17 (0x11)
  .maxstack  8
  IL_0000:  call       uint64 Microsoft.Kinect.NativeMethods::NuiDebugGetFailureStack()
  IL_0005:  stsfld     uint64 Microsoft.Kinect.KinectSensor::failureStackPointer
  IL_000a:  ldc.i4.0
  IL_000b:  stsfld     bool Microsoft.Kinect.KinectSensor::_unsupportedMessageShown
  IL_0010:  ret
} // end of method KinectSensor::.cctor```
fresh salmon
#

Okay before we dive in blindly, run the debugger for your Unity project, run the game and it'll break where the exception happens (was in a script's Start method if I remember correctly)

#

Then post the full exception stacktrace

light creek
#

Do I jsut press this?

#

The code is attached to unity

fresh salmon
#

Yeah that should be good

light creek
#

I pressed it. Now Where do I find the stacktrace?

fresh salmon
#

It'll break when the exception happens

#

VS will get the focus and on the line of code it happened it'll be clearly marked

#

Unless Unity messes with that of course

light creek
#

it didn;t break

fresh salmon
#

Did it log the exception?

light creek
#

yes

fresh salmon
#

So it's not breaking, great
Click on the error in the console and look at the bottom part, the full message will be there

light creek
fresh salmon
#

Meh not very explicit. back to the static constructor code then

#
IL_0000:  call       uint64 Microsoft.Kinect.NativeMethods::NuiDebugGetFailureStack()

It calls this. Find NativeMethods.NuiDebugGetFailureStack() and post its contents

light creek
#
        uint64  NuiDebugGetFailureStack() cil managed preservesig
{
}```
fresh salmon
#

Ah, external call

#

Do you have that "kinect10.dll" somewhere?

light creek
#

I don't remember seeing it anywhere

#

Jsut started a search on this pc

#

it's i nsystem32

fresh salmon
#

Hm can you try something out for me? In the C# code comment out the Debug.Log call. Add this thing in the class

[DllImport("Kinect10.dll")]
static extern ulong NuiDebugGetFailureStack();

And in Start call that, and log what it returns

#

(misspelled method name -- edited)

light creek
#

I thin kI need some namespace

fresh salmon
#

Yes, hover over the error and click the light bulb icon

light creek
#

hmm

fresh salmon
#

Hmmm not normal

#

System.Runtime.InteropServices is the namespace

light creek
fresh salmon
#

Oh yeah, you didn't hover over the error

#

With the mouse

light creek
fresh salmon
#

We're advancing, the Kinect10.dll is the one throwing

light creek
#
using System.Collections.Generic;
using UnityEngine;
using Microsoft.Kinect;
using System.Runtime.InteropServices;

public class kinectScript : MonoBehaviour
{
    [DllImport("Kinect10.dll")] static extern ulong NuiDebugGetFailureStack();
    // Start is called before the first frame update
    void Start()
    {
        // Debug.Log(KinectSensor.KinectSensors.Count);
        Debug.Log(NuiDebugGetFailureStack());
    }

    // Update is called once per frame
    void Update()
    {
        
    }
} ```
fresh salmon
#

Not sure what to do from this point though

light creek
#

decompile it?

fresh salmon
#

Probably not IL that one

light creek
#

What is IL?

fresh salmon
#

Intermediate Language, the language all .NET languages compile to. The static constructor you decompiled had some

light creek
#

I have no Idea which one is it referencing:

fresh salmon
#

The first one if your system is 64bit, maybe??

light creek
#

It fails to decompile

fresh salmon
#

Yeah so it wasn't developed with any .NET language

#

I'm pretty much out of ideas here, the last one being "drag-drop the Kinect10.dll into your Assets aside the Microsoft.Kinect one"

light creek
#

how can it not be found when it's literally in the assets folder

fresh salmon
#

If you put a path in the DllImport attribute, I don't think it'll work

#

It doesn't use paths, if I remember correctly

light creek
#

but that same method is not called when the dll works as intended, right?

fresh salmon
#

It gets called and something inside of it throws
Here it doesn't even manage to locate the file

light creek
#

waht if I do taht in the console application?

fresh salmon
#

It'll work, if the Kinect DLL works in the console app

#

You get the DllNotFound when you run the code because .NET uses lazy loading, it'll attempt to locate and load the very first time you reference it, not when the whole game starts up

light creek
fresh salmon
#

Oh well, then that's probably what also happens within Unity. You said you were using Kinect V2 no?

light creek
#

no, i'm using the xbox 360 kinect

#

yes, in fact it's the same exception

#

OR maybe becasue there are two such named files in my pc

#

and it doesn't know which one to refrence?

fresh salmon
#

Nah it's for the executable to auto-select one depending on whether you're running 32bit or 64bit

#

So that throws, and the DLL uses that, so logically you can't use the DLL.

light creek
#

But when the Microsoft.Kinect.dll is used in the console app, it calls the same method and it doesn't throw?

fresh salmon
#

And I have no idea why

#

They install a SDK and unity packages

light creek
#

but they use the 2.0 sdk

fresh salmon
#

Even the V2 is discontinued. See if you can find the SDK, but for V1

light creek
#

I can and I do have it on my pc, but the documentation doesn't exist

stone crag
#

hi, is there any way to use the "get spectrum data" but with the computer sound like if i put a video on youtube it detects it?

river portal
#

I hope this is the right channel to ask for feedback

#

I had a working title 3 days ago, now I need help, fast

austere jewel
#

You should actually ask a question
People don't want to have to ask for details, you should be transparent upfront

river portal
#

It's hard to define the issue

#

Basically I have all the code set up right

#

but now basic functions like ontriggerenter events are not working

#

as well as cloth component meshes are missing

#

it used to work on the editor, now it's unplayable

#

I did not change single line of code

sly grove
river portal
#

๐Ÿ˜ฆ

#

I see no errors, does unity games have a backdoor that would let this happen?

#

or the engine itself maybe

sly grove
undone coral
river portal
#

<_<

#

Hard to find priests in istanbul though.

undone coral
#

you don't need to interact with any of the DLLs this way

lyric dragon
thin obsidian
river portal
#

this is happening on actual released builds alongside the editor

#

so I did not

obtuse flume
#

https://pastecode.io/s/nwgpy2rw

I would like feedback on this system I am planning: It is a behavior timeline for enemies and projectiles to save myself time and confusion. It will have an instruction type and tweakable fields for the specific instruction.

Questions:

  • Is there a cleaner way to implement the TimelineEntry classes than what I am testing here? (Worried about having a lot of repeated code)
  • Is this a common way to achieve more complex enemy and projectile movements/behavior?
pliant crest
#

might wanna make TimeLineEntry an abstract class

obtuse flume
pliant crest
#

rip

pale pier
dapper nest
#

I know there aren't any "best" way to implement an ability system, but does anyone have any good resources/references to check out for ways to design a event based ability system. Alternatively some learning resources. Imagine the type of abilities that would be common in TCGs. OnAttack, OnDamage, OnDeath, OnFriendlySummon etc etc.

low mesa
#

Hello everyone!
We are developing a mobile game and
we have integrated Unity Remote to our game, we are using it for version number check. Not a big deal.

The issue we have found is in some cases this is not accessible for every users. Like we have one problem from Malaysia, and another one from Vietnam. But we have multiple other people from the same (and other) country who have no problem at all with this feature.

In all cases we have asked for clean installs.

Have anybody ever encountered an issue like this?
(please add me or use reply)

turbid tinsel
low mesa
upbeat path
low mesa
upbeat path
#

their ISP

#

@low mesa Did you try implementing a ping to your cloud service to see if it is reachable?

flint sage
#

Could be many things really, from ad blockers to local network problems to anyone in the middle blocking the signal

#

With remote config systems you'll always have a % of users that won't be able to reach it for various reasons

low mesa
low mesa
flint sage
#

Yes

#

We've got users that can authenticate and load their cloud saves but can't load remote configs for some reason

low mesa
upbeat path
#

It applies to any network usage, you cannot take it for granted that it will work so you need to cater for that

flint sage
#

Exactly, even if they seemingly have got internet access there's still so many things that can fail

#

There can of course still be an issue in your configuration somewhere

upbeat path
#

config issue should, generally, apply to all users not just a sub-set

flint sage
#

Not necessarily? You can have plenty of issues based on device settings that cause connection issues

low mesa
#

yes, now my Malaysian partner reports me that the rem. conf. works with VPN.

Does this means it's an ISP problem?

upbeat path
#

yes, probably

low mesa
#

Thank you guys for your insights!
We will try the game with a different ISP / access point and see what we get.
The majority of the game runs on cloud scripts (Azure btw) and this is quite an issue we have to deal with.

upbeat path
#

Try switching to AWS

low mesa
# upbeat path Try switching to AWS

yes I had that recommendation too. I just don't like to diversify our tech stack that much. Eventually we will, but eh... lots of hustle...

upbeat path
flint sage
#

We use GCP and Playfab(Azure), both work fine imo

upbeat path
flint sage
#

Nope, mostly western countries

#

We do have a bunch of JP users though and afaik they don't have any issues

upbeat path
#

Japan uses a different internet backbone than most of the Far East

thorny lion
#
[ExecuteAlways]
public abstract class Single : MonoBehaviour
{
    protected static Single single { get; private set; }

#if UNITY_EDITOR

    void Update() {
        var copies = FindObjectsOfType<Single>();
        if (copies.Length > 1) {
            Debug.LogException(new System.Exception($"{this} ON {gameObject} MUST BE SINGLE"));
        }
    }

#endif

    protected virtual void Awake() {
        var copies = FindObjectsOfType<Single>();
        if (copies.Length > 1) {
            Debug.LogException(new System.Exception($"{this} ON {gameObject} MUST BE SINGLE"));
        }
        else {
            single = this;
        }
    }
}

Have I just created a singleton that works good?

flint sage
#

Nope

thorny lion
#

y

flint sage
#

I guess it's fine as long as it doesn't persist between scenes or you'll never load it additively into another scene

#

But it not persisting (or creating itself) means that you can't access it in all scenes

#

And thus it is not a true singleton as it'll be null in some scenes

thorny lion
#

ah yeah sceneswise it is garbage

#

I only use one scene in all of my games though xd

shadow seal
#

I don't see the use of the Update method

flint sage
#

Most singleton issues imo come from switching scenes (and testability but yours sucks there too)

shadow seal
#

Any new Single uses it's Awake method and should then destroy itself if there's another

#

So the Update method is just useless

thorny lion
#

Why would you ever want a new Single?

#

like instantiate a game object?

shadow seal
#

I didn't say to new it

thorny lion
#

you did

shadow seal
#

I mean new as in the English word

#

No, because I would have used a code block

#

New is a word in the English language

thorny lion
#

ok got you

shadow seal
#

Any subsequent instances of Single that appear use their Awake method to destroy themselves

#

Well, they ought to destroy themselves

flint sage
#

Well there's no destroy atm so it doesn't

#

But yes

shadow seal
#

But they certainly won't assign themselves

flint sage
#

There's this long ass twitter thread about good singletons somewhere

#

By the friendly neighbor hood @final steeple https://twitter.com/thezombiekiller/status/1488926918712107009

#unitytips Let's talk singletons. Love or hate them, they're an extremely common pattern in Unity gamesโ€”for good reason. The engine itself even has some built-in! (kinda)

However, I often see developers implement the pattern in very error-prone or overly-complex ways.

(thread)

#

Their name is a bit of an oxymoron

thorny lion
#

I see I am most likely misunderstanding Singleton idea. So listen, I have written this script to have a single gameobject in my scene that has the exclusive privilege to have this mono on it. So called unique scripts. One script of mine is Themes.cs that rules the part of UI coloring and I don't ever need more than one of it. Is my code good in such a case?

flint sage
#

I mean it's fine

regal lava
#

Yeah, there's nothing wrong with that. I usually avoid them, but they make total sense if you are just using a single instance of the class.

undone coral
undone coral
# obtuse flume https://pastecode.io/s/nwgpy2rw I would like feedback on this system I am plann...

you are reinventing tracing. you can use something like opentracing / jaeger to record spans, which are like profiler samples except they can be arbitrarily long and finished anywhere. then you can load those traces in a variety of tools, like Chrome. otherwise, you can use the Unity Profiler to show you traces (samples) of any duration by creating a dummy thread, and starting and stopping samples on it.

kindred night
#

Hi guys! So, I have ran into a issue with my game where I have some gas enemies and I want them (if they are at a certain range) to blend which eachother. How could one write a script amount blending shapes?

#

My enemies as of right now are simple spheres, so maybe thats easier to work with?

undone coral
kindred night
#

yeah! something of that sort

undone coral
#

these are called metaballs

kindred night
#

okay i will check it out

#

thank you!

rugged radish
#

is there a cheap way to swap buffers in a compute shader ? an equivalent to this c# code

List<int> a = { ... };
List<int> b = { ... };
List<int> temp = b;
b = a;
a = temp;
#

in the quick and dirty implementation I just readback and swap on the CPU, but now I want to get rid of that step to make it faster

#

current plan is to use a counter, check for even/odd pass inside the shader, and use conditions to switch between buffers, but if I can change references like in any general language, I'd like to do just that

sly grove
#

So to select buffer a set weight to 1. Buffer b set weight to 0

#

You can't just swap references afaik

#

Could be wrong

rugged radish
#

I like that ๐Ÿ‘ but I also need to write to one of the buffers

sly grove
#

You can do a similar trick for writing

rugged radish
rugged radish
obtuse flume
abstract folio
#

@obtuse flume just looked at your post. only thing I would do different is notifications: public override void Execute(GameObject receiver, out Func<bool> finishCheck) rather than return a function the caller wil need to poll- I would have the caller subscribe to an event, then trigger it when the step is done.

#

(you could do the subscription in that function, the user need only pass the event-subscription function to be called.)

thorny lion
#

Generic classes. How can I assign a value to single during inheritance?

abstract folio
thorny lion
#

i mean class : class

abstract folio
#

I understand the inheritance, not the "during" part. do you mean on startup?

thorny lion
#

I mean when it happens

sly grove
sly grove
thorny lion
#

ok wait'

sly grove
#

inheritance is not a thing that "happens" at a certain time. It's a description of the nature of your types

obtuse flume
#

Actually the logic would need updates for actions that happen over time so maybe there will also need to be an Update function in the entries

abstract folio
#

timers and stuff-- prolly- depends on your logic/what your doing.

thorny lion
sly grove
#

Do you know what a Type variable is?

thorny lion
#

object

sly grove
#

Ah shit ok that's a generic type parameter

#

so it's not actually System.Type

#

this is very confusing

thorny lion
#

yeah it is T

sly grove
#

the fact that you've used the names Single and Type here are incredibly confusing to my C# brain
Those are both builtin C# things.

zenith ginkgo
#

Unsure where to post this, I like to think optimizing is an advanced topic, anyone know how to optimize these big 3 (excluding the rendering, can't really fix that)

abstract folio
sly grove
thorny lion
sly grove
#

what did you mean by during inheritance

#

is this in Awake?

#

You blurred it all ๐Ÿคฃ

thorny lion
# abstract folio if your not constructing the Single<T> object yourself (your not since it's deri...
[ExecuteAlways]
public abstract class Single<Type> : MonoBehaviour
{
    protected static Type single { get; private set; }

#if UNITY_EDITOR

    void Update() {
        var copies = FindObjectsOfType<Single<Type>>();
        if (copies.Length > 1) {
            Debug.LogException(new System.Exception($"{this} ON {gameObject} MUST BE SINGLE"));
        }
    }

#endif

    protected virtual void Awake() {
        var copies = FindObjectsOfType<Single<Type>>();
        if (copies.Length > 1) {
            Debug.LogException(new System.Exception($"{this} ON {gameObject} MUST BE SINGLE"));
        }
        else {
            //single = ;
        }
    }
}
#

it is on awake

shadow seal
#

Well I assume it was blurred because earlier they were told it's not optimal

#

I see you still have the useless Update

thorny lion
#

unity editor update

shadow seal
#

Still useless

thorny lion
#

still thank you for help

abstract folio
thorny lion
#

hm

#

didn't help anyways

#

Idk it's hard

abstract folio
#

that will also make it clearer where you can/cannot assign a value.. in this class you cannot, because this class does not know what Type T is. you CAN define a specific descendant, that DOES define the type e.g. class Desc: Single<int> in HERE you could assign an int value to the "single" member.

#

class Desc: Single<float> <- in this class you can assign a float value to "single"

thorny lion
#

oh wait do you say it has been assigned from the beginning just because my single variable is T and class'es <*> is T too?

#
[ExecuteAlways]
public abstract class Single<T> : MonoBehaviour
{
    protected static T single { get; private set; }

#if UNITY_EDITOR

    protected virtual void Update() {
        var copies = FindObjectsOfType<Single<T>>();
        if (copies.Length > 1) {
            Debug.LogException(new System.Exception($"{this} ON {gameObject} MUST BE SINGLE"));
        }
    }

#endif
}

then I can do just that

#

(thank you(if it helps))

abstract folio
undone coral
#

when you have a game built out of a bunch of decoupled stuff ("distributed" by another name), OpenTracing.ISpan is designed to help you record what happened. this has the benefit of working with all your code everywhere

#

@obtuse flume i misunderstood, you want a way to sequence things

#

you should use code to do that

#

you shouldn't design it in the inspector

#

try to build out the things you need from static async methods first

devout dagger
#

Can someone DM who is familiar with Photon Fusion?? i need help spawning game objects

obtuse flume
# undone coral you shouldn't design it in the inspector

My enemies are all based on ScriptableObjects though. If I did it all within code, how would I re-use logic with different values? Ex. one enemy that moves to the left at 5 units per second vs one enemy that moves to the right at 3 units per second. I would still need a way to pass those values in the inspector.

hollow rapids
#

@obtuse flume I like yo use jsons with all my config n.n

#

@obtuse flume For example:

{
    "items": [
        {
            "id": "smg01",
            "name": "SMG 01",
            "damage": 20,
            "equipment": {
                "slot_name": 2,
                "player_prefab_path": "SM_Wep_SMG_01 - Player Variant"
            }
        },
        {
            "id": "pistol01",
            "name": "Pistol 01",
            "damage": 10,
            "equipment": {
                "slot_name": 2,
                "player_prefab_path": "SM_Wep_Pistol_01 - Player Variant"
            }
        }
    ]
}
obtuse flume
hollow rapids
#

It is n.n I recommend the newtonsoft package, it's pretty good

#

I also use it to save my game

obtuse flume
abstract folio
#

Trees. I have too many! Iโ€™m currently grouping treeโ€™s into 400 different โ€œarrangementsโ€. The arrangements contain up to X (currently 40) trees, in various layout and quantities. At startup, I dynamically generate a mesh for each of these arrangements, and randomly assign one arrangement to each โ€œtileโ€ of my map.
I then group together โ€œchunksโ€ of these arrangements for the various sections of the map. I use a loop to go through each chunk and another loop inside the chunk to display all 400 arrangements using DrawMeshInstanced (arrangements that arenโ€™t used in the chunk are skipped).
As the camera moves around, I change which โ€œchunksโ€ will be drawn. (tests show this has relatively minimal impact on performance)
Alas, this is STILL too much for my poor GPU to handle- enabling tree display knocks my frame rate down from 70โ€™s-80โ€™s down to 10โ€™s 20โ€™s.
I should also mention all trees are simple tetrahedrons (only 4 tris โ€“ per tree), through obviously the arrangement meshes usually contain more.
The only solution I can dream up is to, at startup, generate a few textures for each arrangement: an image of the arrangement rendered from a few different view angles. Then, if the tile is more than X units from the camera- I display a quad, with the texture, rather than a mesh with many triโ€™s to be rendered. This seems like a lot of work, so wanted to see if anyone had other ideas before I get down into it.

#

oh.. re-reading this.. I don't need the "bottom" tri for my trees- that knocked em down from 4 to 3 tris- a 25% tri reduction right there.... thanks rubber ducks lol!

compact ingot
undone coral
# obtuse flume https://gyazo.com/cb029aef8e0111dbca50d91c7a909ddd/ Here is this if it helps you...

you should really do it as

// really this is an "Actor" or "Entity" or "Npc"
public class Enemy : MonoBehaviour {
 async UniTask Teleport(Vector2 localTranslation) {...}
 async UniTask ShootProjectile(...) {...}
}

// inherit, or compose, doesn't matter
[RequireComponent(typeof(Enemy))]
public class Bat : MonoBehaviour {
 public Enemy enemy;
 public float pauseDurationSeconds;
 public Vector2 localTranslation;
 void Start() {
  enemy = GetComponent<Enemy();
  BatPatrol().Forget();
 }
 // you can later promote this to a Patrol method, 
 // that takes args, into your Enemy class
 private async UniTask BatPatrol() {
  // easy to wire this up with being destroyed,
  // external events like getting killed, etc.
  while (isActiveAndEnabled) {
   await enemy.Teleport(localTranslation);
   await UniTask.Delay(TimeSpan.FromSeconds(pauseDurationSeconds));
   await enemy.Teleport(-localTranslation);
   await UniTask.Delay(TimeSpan.FromSeconds(pauseDurationSeconds));
  }
 }
}
#

do you see how the code is a timeline, and also, it already has built in reusability and ways to express stuff like a patrol, that is intuitive, etc. etc.

abstract folio
undone coral
#

@obtuse flume like why reinvent C# in your inspector

compact ingot
# abstract folio you mean geometry shader, or somthing else?

Have a look at assets like infinigrass or vegetation studio and their approach to rendering lots of vegetation, a gdc talk on a similar system in HZD https://m.youtube.com/watch?v=wavnKZNSYqU

GDC

In this 2018 GDC session, Guerrilla Games' Gilbert Sanders discusses what the studio learned in order to bring the lush and vibrant vegetation of Horizon Zero Dawn to PS4 while keeping an eye on overall performance.

Register for GDC: https://ubm.io/341ZiaZ

Join the GDC mailing list: http://www.gdconf.com/subscribe

Follow GDC on Twitter: https...

โ–ถ Play video
obtuse flume
undone coral
#

you are reinventing C# in a scriptable object, which is notoriously error prone

#

and the decoupled-by-default architecture of Unity + Prefabs is pretty much purpose built for platformer / hack and slash adventures like what you are making

abstract folio
compact ingot
undone coral
#

it is one of the few places where decoupled (drag and drop a prefab, and the prefab's code figures out its context "locally") really shines

#

so you should have had a prefab for "Flappy Book" @obtuse flume

#

instead of a scriptable object

#

then all that other data would go into a component on that prefab

#

prefabs and scriptable objects are duals.

#

@obtuse flume anyway you are in advanced code

#

you might not be open to making these changes at this point. what i am saying is true, you cannot bend reality and reinvent c# in your inspector window, it will come out poorly

#

that means you will have to ditch this stuff, eventually, to have a bug free game. or you will have a lot of bugs

#

i think the async method i wrote is really comprehensible and ismple

#

much simpler than a scriptable object, and having a timeline data, etc.

#

however, i think you like that scriptable objects are like, a thing you can sort of fill out

#

imo you should do the spreadsheet-esque design work separately from unity

#

a scriptable object, the way you are using it, is to help you think, but it's not a very useful way to engineer a game. does that make sense?

#

in the same way that outlines help you think, but you do not deliver a short story that is made out of bullet points.

fallen hearth
#

I'm trying to load a png blob from a MySQL server but it keeps giving me a red question mark.
When I used the system.IO to create a png file, it works and the image does load meaning the bytes are correct for png.
The Image is 112 x 112 pixels in size

byte[] img = (byte[])rdr["HeroArt"];
Texture2D tex = new Texture2D(112, 112, TextureFormat.RGBA32, false);
tex.LoadImage(img);
System.IO.File.WriteAllBytes("E:\\Testimage.png",  img); //For testing purposes

tex.Apply();
test.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0f, 0f));
undone coral
#

@obtuse flume also consider that i could write maybe 10 more lines of code, to implement Teleport

#

and i have achieved all the behaviors everywhere, in maybe 1/100th of the space that you have

#

intellectual space inside our heads, and space in the C# file

obtuse flume
# undone coral however, i think you like that scriptable objects are like, a thing you can sort...

Definitely do like that part of it. Also: I believe the reason I wanted to make every enemy have the same structure is to make it friendlier with programming multiplayer (Mirror). When serializing enemies over the network, all I have to pass is the enemy's name and then the receiving client can look up the data and have it all present from the ScriptableObject, instead of having to ensure all the pieces serialize correctly.

Thinking about it now though, I could just have prefabs and achieve the same thing. The one hesitation I have is figuring out how to make sure the prefabs I create have all the required parts. If I want to make a change to all enemies' prefab, how would I prevent needing to go through tens of other prefabs and making the change?

fallen hearth
undone coral
#

also, tens of prefabs is not many

#

prefabs support an inheritance hierarchy that is really useful

#

you can also still mutli select and edit

#

lots of ways to skin this cat

undone coral
undone coral
#

not impossible just hard

#

you wouldn't synchronize the state of the timeline. there are ways to "synchronize" (serialize and resume later) a c# async method, but that's some Mega Real C# science. you would only synchronize the visible, in world side effects, like the current position, which is a NetworkTransform

#

if you want to synchronize something logical, you cannot make a decoupled game

#

since your timeline is C# in disguise, if it is going to do anything more complex than an animation (which you CAN synchronize), you are going to be engineering a distributed database in disguise, which you do not want to do

#

so for example, if you want a behavior async UniTask WaitUntilPlayerIsNear(float radius)

#

synchronizing that logically is going to be crazy hard. at that point you should commit to synchronizing transforms, rotations and other side effects

#

that are like, part of a category we should call "animations"

obtuse flume
undone coral
#

and to make it multiplayer, start with NetworkTransform

#

focus on, "the stuff that i am going to make synchronized over the network is only stuff that is visible to the player"

#

so โœ… health, position and current sprite being shown, but โŒ progress along this timeline

obtuse flume
undone coral
#

great

obtuse flume
#

and of course projectile spawns

undone coral
#

yeah so i think you're in a good place

#

we're just making a little change to not try to overengineer the timeline

#

it will be a big distraction

#

it does look really nice

#

but everything looks hot so far

#

it might be too low ROI for you to make this editor panel

#

@obtuse flume one last thing, are you familiar with TaskCompletionSource?

obtuse flume
#

only took me like 1 hour to do the timeline since i was recycling from this (this may be overengineering too)

undone coral
#

this is a way to signal that something happened into an async method

#

for example

#

and i think this is essential to understanding why this approach is so good

#

@obtuse flume let's say we had a complete, working door component

// UniTaskCompletionSource example
class Door : MonoBehaviour {
  // this can also be an IObservable... see later
  public UniTaskCompletionSource<bool> doorState = new();
  private bool m_DoorState;
  [SerializeField] private Animator m_Animator;
  [SerializeField] private InputActionReference m_OpenAction;
  [SerializeField] private float m_InteractionRadius;
  [SerializeField] private Collider m_Collider;
  public bool isOpen => m_DoorState;
  void Start() {
   // todo: unsubscribe, but also use UniRx instead
   m_OpenAction.action.performed += ctx => {
    // or whatever it is, it's not user id but it's something like that
    // if the door is too far away when you pressed the door open button,
    // don't do anything
    var playersDistanceFromDoor =
        (GameController.instance.players[ctx.userId].transform.position
         - transform.position).magnitude;
    if (playersDistanceFromDoor > m_InteractionRadius) { return; }
    Toggle();
   };
  }
  void Toggle() {
   m_DoorState = !m_DoorState;
   m_Animator.SetBool("Door State", m_DoorState);
   m_Collider.enabled = !m_DoorState;
   doorState.TrySetResult(m_DoorState);
  }
}
#

observe how simple this is.

#

and it pretty much does everything robustly in a decoupled way

#

now lets make an enemy that waits until the door is opened before it does something

#
class SleepingSkeleton : MonoBehaviour {
  ...
  [SerializeField] private Door m_Door;
  private async UniTask SleepingSkeletonBehavior() {
   // wait for the door to open
   var isOpen = m_Door.isOpen;
   while (!isOpen) {
    isOpen = await m_Door.doorState;
   }
   ...
  }
}
#

it would be even more succinct to use UniRx reactive properties ofr something like this, which can be awaited

#

but i don't wanna introduce too much stuff at once

#

the reason i'm talking about it is because the english language description of the behavior of the enemy will look almost exactly like your little async methods

#

once you start using these three things - unitask, unirx and async/await generally - you can also solve bugs by thinking in english, instead of updateloopese

#

for example, i knew i had to deal with the door possibly being already open

#

and what if the player is already inside the room with the skeleton?

#

you can UniTask.WhenAll multiple conditions

#

it's very powerful, more powerful than a timeline

#

or a behavior tree. it looks justl ike English!

#

@obtuse flume is this helpful?

obtuse flume
undone coral
#

once you decide you want this WaitUntilDoorOpens behaviour everywhere

undone coral
#

which you can't do stuff every frame that isn't rendering in a multiplayer game

#

also, it doesn't look like english

obtuse flume
#

Yea that does sound more like english. Like
While the door isn't open, await for it to be open

#

instead of: if door is open and it wasn't last open do this

undone coral
#

yeah

#

you can still wait until a condition is true. that's fine. but it's not something you can do in multiplayer anyway

#

you might "miss" something

obtuse flume
#

so the diff between this and a coroutine is that this would allow tasks to interact with eachother's progress?

undone coral
#

it's like using Input.GetMouseButtonDown

undone coral
#

you owuld use an event via unirx for something like this

obtuse flume
undone coral
#

@obtuse flume UniTask's stuff works

#

it's from the UniTask package

#

you don't want to use plain async in unity

#

too warty

low mesa
undone coral
#

good luck out there

obtuse flume
#

@undone coral got the enemies restructured, I just have this one problem:

#

Is there a way to cancel an async task when the enemy is destroyed?

#
        protected async UniTask FollowForSeconds(Transform followTransform, float speed, float seconds)
        {
            var doneTime = Time.time + seconds;

            while (Time.time < doneTime)
            {
                Rb2d.velocity = (followTransform.transform.position - transform.position).normalized * speed;
                await UniTask.WaitForFixedUpdate();
            }
        }
west scarab
obtuse flume
undone coral
#

if you want the unitask helper for it

#

how do you feel? big improvement?

#

i like that the way it is written makes PERFECT SENSE

#

and i can comprehend that FollowForSeconds does EXACTLY what it says

west scarab
undone coral
#

oh sick

#

that's great

west scarab
#

But I feel like coroutines still have their place with cancellation being such a pain

undone coral
west scarab
#

What do you mean?

undone coral
#

like the custom async executor that he uses

#

it could just check if the object is destroyed if you configured the task to do so

#

on every await

west scarab
#

Not ideal from a performance aspect

undone coral
#

for tasks started from an object. i actually odn't know how to get the context of the object whose Start / Update / etc is currently being called

#

from some static or whatever. not sure if unity sets that. but it would not be that hard to do

#

well you are awaiting anyway, presumable it is a bonafide async thing you are awaiting

west scarab
#

Could just be another function returning Task ๐Ÿคท

undone coral
#

yes. "don't do that." but yeah, that happens

#

@compact ingot look at @obtuse flume he's doing it. he's doing the async game logic thing and it looks great.

west scarab
undone coral
# west scarab Why shouldn't you do it?

you definitely can, it is probably the only option for things that are meant to be overloaded. but if it's stuff like this, if you know it's a regular function, make the simplest signature that it can have

#

since you control all the source

#

if you need to promote it to be async, you can always refactor that later

west scarab
#

Guess it depends on how your game works. Lots of things can be async

undone coral
#

like he started only 4 hours ago

#

i'm so proud ๐Ÿฅน

obtuse flume
west scarab
#

Do you plan to just duplicate the prefab then if you need enemies with e.g. different health?

obtuse flume
#

And then yeah I just change what needs changing

west scarab
#

Alright, I was just wondering how you were planning to store your different entity types then

undone coral
#

@obtuse flume okay i don't wanna push my luck but here's one more thing...

obtuse flume
undone coral
#
using UniRx;

class Actor {
 [SerializeField] IntReactiveProperty m_Health = new();
 public IReadOnlyReactiveProperty<int> health => m_Health;

 private Subject<Actor> m_SentToGraveyardBy = new();
 public IObservable<Actor> OnSentToGraveyardBy() => m_SentToGraveyard;
 ...
 public void DamageThis(Actor source, int amount) {
  m_Health.Value -= amount;
  if (m_Health.Value < 0) {
    m_SentToGraveyardBy.OnNext(source);
  }
 }
 ...
}
[RequireComponent(typeof(Actor))]
class Boss : MonoBehaviour {
 public Actor actor;
 void Start() {
  BossBehavior().Forget();
 }
 public async UniTask BossBehavior() {
  await actor.health.Where(hp < 20).First();
  // todo: what about overkill? it's legible if you
  // deal with the bug here.
  await TransformIntoForm2();
  await actor.health.Where(hp < 3).First();
  await TransformIntoForm3();
  var whoKilledMe = await actor.OnSentToGraveyardBy().First();
  whoKilledMe.GetComponent<PlayerInventory>().AddGold(100);
 }
}

@obtuse flume

#

"oh i have to deal with overkill"

obtuse flume
undone coral
obtuse flume
#

So this waits for the Actor that kills the boss then awards them gold.

#

So obviously for overkill you wouldn't want it to go through transformation steps

undone coral
#
class Actor /*...*/ {
 ...
 // whenever you subscribe to this,
 // a behaviour subject REPLAYS all the events
 // that were OnNext'd through it
 private BehaviourSubject<Actor> m_SentToGraveyardBy = new();
}

[RequireComponent(typeof(Actor))]
class Boss : MonoBehaviour {
 public Actor actor;
 void Start() {
  BossBehavior().Forget();
 }
 public async UniTask BossBehavior() {
  await foreach (var health in actor.health.DistinctUntilChanged()) {
   if (3 < health && health <= 20) {
    await TransformIntoForm1();
   } else if (0 < health <= 3) {
    await TransformIntoForm2();
   } else if (health < 0) {
    var whoKilledMe = await actor.OnSentToGraveyardBy().First();
    whoKilledMe.GetComponent<PlayerInventory>().AddGold(100);
    break;
   } 
  }
 }
}
obtuse flume
undone coral
#

yep. it will wait until the health is changed, and when it has, sets health to that value and executes the loop

#

there are many ways to skin this cat, but what's essential is you can sort of make this look like something reactive sometimes, and sometimes you canb make it linear. you can be creative

#

and it's very expressive

obtuse flume
#

Hard to read for me, I've never heard of half of these things

undone coral
#

okay yeah this is a much tougher one

#

you don't have to go this far

#

...yet

#

but you are already equipped to do it

#

like when you want to make things more reactive / wait for events

#

unirx is useful

west scarab
#

This feels like an indoctrination to reactive programming ๐Ÿ˜…

undone coral
#

you might have seen in the unitask docs already await button.OnClickAsync()

#

there's a way to do that a lot of different ways

#

maybe it's a door that every player has to click on to open.

#

or you have to kill 10 enemies

#

or whatever

#

you don't want to make a KilledTenEnemies taskcompletionsource. maybe you just want a counter of the number of enemies killed, and then Where it.

#

anyway you see some stuff there

#

you can deal with the overkill a lot of ways, but this was just an example

#

@obtuse flume here it is without await foreach:

class Actor /*...*/ {
 ...
 // whenever you subscribe to this,
 // a behaviour subject REPLAYS all the events
 // that were OnNext'd through it
 private BehaviourSubject<Actor> m_SentToGraveyardBy = new();
}

[RequireComponent(typeof(Actor))]
class Boss : MonoBehaviour {
 public Actor actor;
 void Start() {
  BossBehavior().Forget();
 }
 public async UniTask BossBehavior() {
  while (true) {
   var health = actor.health.Value;
   if (3 < health && health <= 20) {
    await TransformIntoForm1();
   } else if (0 < health <= 3) {
    await TransformIntoForm2();
   } else if (health < 0) {
    var whoKilledMe = await actor.OnSentToGraveyardBy().First();
    whoKilledMe.GetComponent<PlayerInventory>().AddGold(100);
    break;
   }
   // wait until the health has changed.
   // lots of ways to skin this cat
   await actor.health.Where(x => x != health).First();
  }
 }
}
#

elsewhere you might have a script that animates the helath specially

#
class ActorHealthAnimator : MonoBehaviour {
 public Actor actor;
 public TMP_Text healthText;
 void Start() {
  actor.health
   // whenever the health changes to a new value
   .DistinctUntilChanged()
   .Subscribe(async health => {
    if (healthText) {
     healthText.text = $"{health}";
     await healthText.DOShake(...);
    }
   })
   // no more OnDestroy() { event -= handler; } !!!
   .AddTo(this);
 }
}
obtuse flume
#

This syntax is so unusual ๐Ÿ˜ต

undone coral
#

@obtuse flume for stuff that is just rendering side effects, like a little text shake animation, the reactive thing is really useful. it gets rid of the updateloopese and the cantankerousness of event += handler, event -= handler;

#

it is but it lets you use linq

#

which can be a pretty nice way to express stuff

#

for decoupled rendering i use unirx / reactive code a lot. very similar to modern web dev

#

however, you can also put the shake on the text label directly into the actor code. really depends - what if the health label is somewhere else? might want to assign a health label that's special for the player, and omit it sometimes for enemies with 1hp, etc.

obtuse flume
#

ok hold on let me make sense of these new things:

undone coral
#

okay, and then i want to show you how you can combine these two things to robustly solve a seemingly really complicated problem. the example i'll work through is

when an actor dies, i potentially want to process a bunch of async stuff, like animations but also spawning other enemies, before i play the death animation, and then destroy it for real

how do i set up those effects in a decoupled way? i want to be able to drag a "Deathrattle" component onto a prefab, and then it Just Works.

#

hmm actually it doesn't striclty need to be reactive

#

to do that

#

it is easy to understand and achieve with async alone

#

really tough to come up with a complex example.

#

reactive stuff is really for rendering

#

if you were making a card game or some kind of turn based game, where you need to have events from the network (which come instantaneously) splay out into animations (which last a long time), it's super useful

#

like if you need to render data, but delayed.

#

@misty glade has some insight into that. he made a multiplayer game that's pretty sick, and the next one will use techniques like these to make things easier to manage

obtuse flume
#
  1. ReactiveProperty just holds a value and you can asynchronously check its value with LINQ. Parallel to yield return new WaitUntil(abc == xyz)
  2. IObservable<Type> returns enumerable(?) values of Type that have been OnNexted to it. Subject<Type> is used to make this work. Using BehaviourSubject instead makes it so you can access the history of the values that have been "pushed" to it in order.
undone coral
#

"deathrattle" (do something when the actor dies) looks like

class Actor : MonoBehaviour {
 async UniTask TakeDamage(Actor source, int amount) {
  health.Value -= amount;
  if (health.Value < 0) {
   var deathrattles = GetComponents<IDeathrattle>();
   foreach (var deathrattle in deathrattles) {
    await deathrattle
      .OnMovingToGraveyard(source, amount);
   }
   Destroy(this);
  }
 }
}

class DeathAnimation : MonoBehavior, IDeathrattle {
 override async UniTask OnMovingToGraveyard(Actor killedBy, int amount) {
  // shake and spawn a tombstone sprite
  await this.DOShake(...);
  tombstoneSprite.SetActive(true);
  await tombstoneSprite...
 }
}