#archived-code-advanced

1 messages · Page 155 of 1

shell grove
#
yield return new WaitUntil(() => Master.time / (notes[btn].Frequency / 44000f) == 0f );
#

that kinda works

#

but it doesn't

#

If only I was good at math

sly grove
#

Why check for equality

#

Just do a > or < check

polar ermine
#

i dunno where this belongs on the code difficulty scale but.
i need to display some "status cards" in a grid, based on what status the player has accrued. (poisoned, flying, injured, etc).
a status card consists of some tooltip text, and a sprite.
the grid starts empty, but i need to add and remove such a card from the grid at any point

my question is, i suppose, what's the best infrastructure to set this up? will i need a scriptable object for each possible status? how do i reference those dynamically to instantiate them into the grid in a way to easily create and apply new statuses as i develop?

cursive horizon
polar ermine
# cursive horizon depending on how they are used, i might just have a hashset of status enums some...

i already am keeping track of a few statuses as enums, i do just need a way to associate a status with a sprite, and have some sort of reference to all existing status associations to instantiate them into the grid.

i suppose im having trouble nailing down the specifics of that setup, as i'd prefer a flexible solution that involves as little boilerplate set up for each time i want to add a new status the game might use.

cursive horizon
# polar ermine i already am keeping track of a few statuses as enums, i do just need a way to a...

Well it depends if you want to mix the presentation with the logic. If you don't mind that, I would say just make an SO for each status instead of an enum and include presentation details there (like the sprite, display name, etc). Then you can have another SO which holds the 'currently available statuses' and put whichever ones you want active in the game into there, and assign that reference to whatever needs access to the statuses.

If you want to keep presentation and logic split, I would keep the statuses as enums and just make a 'StatusDisplay' class, and then make an SO with a dictionary of status->StatusDisplay which you reference in your view component. Unity doesn't serialize dictionaries out of the box so that approach is easier if you have Odin, but you can work around that limitation if you want to.

#

I tend to like the second approach, but I also use Odin which makes it pretty simple. One advantage there is that if you want to sometimes display statuses differently (like maybe there's a 'status glossary' which uses fancier sprites and has a more in depth description). Associating the view data with the status directly can get confusing if you have multiple similar presentations of the same value

polar ermine
# cursive horizon I tend to like the second approach, but I also use Odin which makes it pretty si...

no odin for me, but i ought to look into it.
having a dictionary of statuses isn't too bad, i think. though my experience is limited, so lmk if my brainstorming is flawed.
a scriptable object (statuses?) that hold a number of statuses (say a serializable status class) which in there I can hold references to each statuses individual sprites and information?
something like (pseudo code)

public class Statuses: ScriptableObject{
  public Status[] status;
}
...
[Serializable]
public class Status{
  public string name;
  public string desc;
  public Sprite sprite;
}
cursive horizon
polar ermine
#

my thought here is that in the inspector i can just add a new entry into the statuses and apply their things once, then reference them elsewhere.

cursive horizon
#

right, and to add a new status you jut have to create a new SO instance and add it to the list

#

which fits you 'minimal boilerplate' goal

#

for the status list, I have a class like:

public class ConfigSet<T> : ScriptableObject {
  public T[] items;
}
#

and then i extend that to create lists of SOs which i can plug and play, cause this pattern ends up being really common

#

also it has some helpers on it like GetRandom

polar ermine
#

hm, alright, awesome, that's super useful
and to reference a particular status, im gonna simply need to have a reference to that Statuses SO on my player, right?

cursive horizon
#

one of the nice things about SOs is that you can reference them from a few places if you need to, just don't go too crazy because they are sorta 'globals'

#

but if you had the player who needs to know about them, and then a ui panel or something, they could just both reference your Statuses list and that's handy

polar ermine
#

for sure for sure.
it's a card game, and each card can have certain statuses applied to them. i'm already using SO's to generate card information and visuals and instantiate multiple cards based off of a single card template prefab, so it's pretty cool that all i need to do is just add one reference to the template's script

cursive horizon
# polar ermine for sure for sure. it's a card game, and each card can have certain statuses app...

Ah, well I would expect statuses in a card game to potentially have very different effects, so I wouldn't try to encapsulate them. I'd probably have some systems whose job it is to handle the effects for whatever status and keep the statuses a 'dumb' enums. In that case, you might not actually need a list of 'all enums' referenced anywhere, because each system would only care about the one(s) it needs to interact with (and can just check if they are active on the player and do nothing if not)

#

depends on the game and what sort of stuff is happening though

#

and that approach does require more boilerplate because each status is handled explicitly (but in my experience, that's actually what I want)

#

so your damage system is actually what would query and apply logic for the 'double damage' status

#

the advantage there is that you keep all of your 'damage logic' in one place, but it can get complex if you have a lot of different statuses

#

still, having that complexity be explicit is better than hiding it in a bunch of objects with OnApply or whatever (imo)

polar ermine
# cursive horizon Ah, well I would expect statuses in a card game to potentially have very differe...

yeah; im probably currently doing it pretty suboptimally, but for the one status i have built up it's simply an enum (flying or grounded), and im already using that enum elsewhere to determine what happens if they get attacked depending on which effect is applied to them

i just wanted a way to link that to a visual for the player, but also i can definitely see it getting more out of hand as i scale the mechanics, as it becomes a case of checking whether or not a status is applied and applying logic based on that for each status

cursive horizon
#

but honestly that sounds fine to me...if you have a lot of statuses and they might be interacting with each other because they all affect 'damage', you might want to force yourself to make all of that explicit and in one place

#

so if you already have that in place and just want to map the statuses to visuals, the dictionary approach sounds good to me

#

there are definitely free extensions that will serialize it for you without odin but i can't speak to them

#

i feel like i'm leading you in circles 😛

polar ermine
#

lmao

#

it's fine, i definitely got a good starting point to at least try

#

im relatively new to the whole unity thing, so i don't mind doing things myself until i'm comfortable enough to use something like odin to just save time

cursive horizon
#

especially for a card game where you want to be able to 'configure' complex cards, i can't imagine building tooling for that in the editor without odin's ability to serialize interfaces

#

well i can imagine it, it just sounds like a big waste of time

#

But yeah, it's always good to run into the problems that tools solve before you reach for them. Just know that odin is dope and will be there for you 😄

polar ermine
#

haha, fair enough. i'll give it a look sooner rather than later. currently there isn't too much complexity that i've needed any third party editor tools, but i know that can change quick

#

odin: noted ✅

cursive horizon
#

you can do that in unity now with [SerializeReference] but I'm not sure what gotchas it comes with

polar ermine
#

ooh, actually... i think i need something for something similar.

#

i have a lot of card components in cards that don't need them and it's gonna be a mess when i expand it further

cursive horizon
#

yeah, eventually you end up with a lot of 'potential complexity' and it's hard to tell how much is active on any given card

polar ermine
#

like, i have a card ability that heals; i don't need components in there to tell me how it affects the card's movement status

#

or what sort of damage it does

#

healing damage

cursive horizon
#

yeah, and it's a similar thing for statuses imo

#

you could try to encapsulate them and have all the possible effects on each status, but I think this way is simpler

#

i spent a bunch of time trying to work around the default serialization ages ago, so doing this is great

#

that said, it's still useful to split your 'editor config' from your 'runtime' config, so you can kinda do both

#

like the 'card editor' might want to have more context for each possible thing that a card can do and show/hide sections, basically just be smarter than 'dropdown with every option in it'

#

but ultimately i do like the runtime version being 'pure data component' based for something like this

polar ermine
#

hm, yeah, i get it a bit better now. definitely sounds useful

#

i've been trying to simplify it with editor scripts but it wasn't worth the effort.

cursive horizon
polar ermine
#

well you're selling me on it!

cursive horizon
#

well apparently it's half off right now...

polar ermine
#

oh shoot

cursive horizon
#

ey you got 20 days!

polar ermine
#

what a bargain

#

hopefully enough to get my paycheck in but it's a pretty good deal anyhow

fierce holly
#

i took a slightly different approach, but what you guys suggested definitely helped me find new solutions and ideas. I was pretty stuck on this, so thanks!

#

don't mind the layer mask, i put it to "water" for testing purposes because i didn't know how to add other layer masks immediately

fierce holly
#

i did make use of the layer mask as you suggested!

undone coral
#

the best thing, in this exact case and nothing else, is to do it in code with a giant switch statement

#

because expressing string formatting is easiest in code

#

you should have a Tooltip class with a static string[] Tooltips(Entity entity) { ... } method that generates all the tooltips

#

trust me, i thought about this a lot, and in my own card game, this was the best way

#

everything else you could do, you'll wind up reinventing string formatting

#

specifically the part where it's easy in code to just... get a thing

#

whereas in a string field, it's hard

#

you'll do a lot of

if (entity.HasStatus(Status.BLAH)) { 
  tooltips.Add($"You are suffering from {entity.GetValue(Values.BLAH)} blah"))
 }
#

you don't want to create a DSL for entity.GetValue or whatever

#

that's just reinventing C#

#

don't do that

#

"what if i have a sprite icon i want to show" return it in the string in a way that's compatible with textmesh pro

#

all this stuff you want to do with text, do it in code

#

my hot take 🎤

polar ermine
#

I actually do have a tooltip class/system that I was using for something else, and I was able to use it for this as well.

#

Though I worry more about my logic system, cause it’s going to get really messy if I don’t learn how to split things up better.

undone coral
#

i don't think you'll earn anything by "splitting" this up

#

there is exactly one UI element that needs the tooltip information

#

that's some tooltip element

#

you can make a single static method that deals with generating the tooltips for anything

#

everything else, you'll just wind up repeating yourself for no gain

#

there's no reason to have a subclass of tooltip, and then make singleton tooltip instances, etc. etc.

#

it's just a ton of ceremony for no gain

#

you don't want the card DSL to be aware of how it affects the tooltips

#

you don't want to encode that there

#

it's too unwieldy

#

just put it all in one place

#

a lot of card games have way too many tooltips

#

because people try to be so pure about it

#

you will inevitably want to customize the tooltips everywhere they appear, so a generic method won't do much for you

polar ermine
#

Yeah I’m using a static tooltip class courtesy of a great YouTube vid I found. It’s been useful thus far.

undone coral
#

okay great

#

unless your game needs to support card design at runtime

#

it's almost always better to have just encoded card behavior as C# code the way XMage does

polar ermine
#

The only card design at runtime I do is setting the sprite and a few details, based on which card is drawn. I’ve one card prefab template and I use SO details on instantiating to fill out the details.

#

Maybe not perfect but it’s given me the least headache once I set it up

undone coral
#

i would suggest something of the form

class Fireball : AbstractBaseCard {
 override IEnumerator Play() {
  var selectTarget = new SelectTarget(TargetSelection.ALL);
  // yields when the player
  // selects the target
  yield return selectTarget;
  var target = selectTarget.target;
  // plays the damage animation
  // deals the damage
  // it's a coroutine
  yield return Game.instance.DealDamage(5, target);
 }
}

@polar ermine

polar ermine
#

Thanks! Saved that for reference. Currently I’m making individual ‘actions’ for any given card, and the attack method reads the action parameter and uses the necessary variables like damage and damage type. An extensible class would be better

undone coral
#

it's just much easier to express what's going on using code

#

because card games are already algorithmic

polar ermine
#

Very true. Literally everything beyond the chosen course of action is behind the scenes calculations lol.

#

The same could be said about a lot but eh

cursive horizon
#

maybe that question doesn't really make sense with how e.g. magic models everything

#

where that would be an artifact which adds +x to cards instead, probably? does magic do any relative calculations?

undone coral
cursive horizon
#

what if i want to show the player ahead of time how much damage a card will do?

#

i guess you can have a CalculateDamage method and call that and pass that result in

undone coral
#

yeah for everything that you need

#

like, just write the code to do it

#

don't make a meta coding blah blah lisp system thing UNLESS you need an editor the end user will interact with

#

because a normal person can't write C#

cursive horizon
#

that isn't really what i would do instead

undone coral
#

well both are totally good

#

i use a DSL

cursive horizon
#

different solutions for different contexts

undone coral
#

but that's because the end user does make stuff

#

yeah

cursive horizon
#

'just write the code' isn't really architecture though 😛

#

where i write the code matters!

undone coral
#

lol

cursive horizon
#

i mostly agree with you

heady bane
#

how do you get asset bundle load from file to work?

#

so I have a folder of asset bundles set up and ready to go

#

I can confirm the asset bundles are in the app.

#

is this because im running the project in the editor and need to use a different directory than the streaming assets directory shown in the example?

minor scaffold
#

Hey guys, I have a quick question. I'm writing an editor script. When I instantiate an object it loses its prefab reference. As you can see in the photo, if I create an object in the scene by drag and drop from prefab to the scene, the object's color is blue and it still inherits from the prefab. But when I instantiate it via script, it becomes "A clone". Is there a way to instantiate the object and not lose the reference of its prefab.

#

I need this because im using PrefabUtility.GetCorrespondingObjectFromSource(TObject componentOrGameObject)

long ivy
minor scaffold
#

idk how I miss that

frank rune
#

my player stopped colliding with the ground

#

what do i do

dusty shell
#

what happens if an axis positional float of an object over/underflows in unity?

will the game crash? simply reposition the object at the other end of the line?

austere jewel
#

I would presume it just goes to positive/negative Infinity and prints warnings to the console if associated with a renderer. 🌈 Check it yourself 🌈

fresh salmon
#

In a checked environment (outside of an unchecked block), it would simply throw an OverflowException. At least, that's what it does for int values, so it should logically be the same for float

#

Update, it doesn't, it just goes to (negative) infinity

frank rune
#

closestPoint() is not working for a tilemapcollider2d

#

what should i use

fresh salmon
#

I could not find any similar issues on the internet, and the Docs for ClosestPoint does not warn about issues on TilemapCollider2D.
The page specifies that it will work with all types deriving from Collider2D

#

Update, TilemapCollider2D indeed inherits from Collider2D

frank rune
#

When I use the mouse position in the parameter it gives me a position on the corner of the entire tilemap

fresh salmon
#

Check the collider's bounds, debug the positions.
Make sure you're converting mouse position (screen space) to world space correctly using Camera:ScreenToWorldPoint

#

An alternative would be calling WorldToCell on the tilemap, to get a specific cell from a specific world position

frank rune
#

thanks!

#

I wasn't converting the mouse position

#

it works now

shell grove
#

I've got it working to end on a 0 in the wavestream

#

Where this is the code that I use

#
yield return new WaitUntil(() => Master.time / ((int) (44000 / notes[btn].Frequency) / 44000f / (int) (44000 / notes[btn].Frequency)) == 0f );
dusty shell
#

@austere jewel @fresh salmon aight thanks alot :D

#

any suggestion on how to prevent players from overflowing their coords?

#

in an open space

#

using death zones?

fresh salmon
#

You'll start getting noticeable float precision issues around 100k, where stuff would start to violently vibrate as you move, so if your map is larger than 200 km long, death zones

dusty shell
fresh salmon
#

Or, move the whole map and player towards the origin of the world

#

Your choice

dusty shell
#

so this is due to float rounding errors?

fresh salmon
#

Yes

dusty shell
#

kk

shell grove
#

That is the playback time in seconds of the currently playing Audioclip.

Master.time

This is the amount of samples in any given Audioclip.

(int) (44000 / notes[btn].Frequency)

This is the frequency of the samples.

 44000f

As you can see, I'm calculating the time in seconds it takes to play 1 sample of the AudioClip. So in theory this should stop as soon as 1 sample has been played.

The problem is that

yield return new WaitUntil()

is apparently too slow to accurately check that, since it's frame depended. My Unity does not run at 44000 fps, though I wish it would 😀

Any suggestions how to solve this problem?

fresh salmon
# dusty shell kk

You can try it for yourself,
Debug.Log(1000000f + 0.1f)
You'll get 1000000 in the console because it can't handle it

dusty shell
#

but would have to work with relative coords then right where everything is dependent on the center

dusty shell
#

yea ive heared about that issue with floats

#

so at 1m it cant actually calculate floats anymore

#

1b*

#

due to the 32bit limit

shell grove
#

Isn't there an equivalent to float as there is BigInt?

dusty shell
#

there is double

#

but its only double accuracy

#

not double size

shell grove
#

halfdouble

dusty shell
#

wait it is

#

64bit

fresh salmon
#

That's where the name comes from.
At larger values it doesn't have enough bits to store the integer part anymore, so it moves the decimal point to the right to allocate more bits to the integer part, in term reducing the bit for the decimal part -> precision issues ensues.
Float = floating point, the decimal point moves left or right according to the needed precision

shell grove
#

Double is more precise than float and can store 64 bits First google result when searching Double or Float

fresh salmon
#

And yes, float is 32 bits, double 64

dusty shell
fresh salmon
#

In C# it's long, a 64 bit integer

dusty shell
#

ah long

shell grove
#

Yeah

shadow seal
#

There is a BigInteger in System.Numerics

dusty shell
#

also i think the biggest primitive C supports is 256bit

shell grove
#

I like the naming shenanigans there, "You want a bigger int? BigInt it is. You want a 16-bit int? SmallInt it is"

fresh salmon
#

Oh yeah C is weird, you can do long long as a data type I think

dusty shell
#

unsigned long long int

shell grove
#

Oh long johnson

dusty shell
#

tho idk the c# equivalent for that

fresh salmon
#

There isn't one

dusty shell
#

🤷‍♀️

fresh salmon
#

Usually long is sufficient enough

dusty shell
#

true

shell grove
#

Anyway, does anyone know a frame independent alternative to WaitUntil() ?

dusty shell
#

yes

#

its called delta timing

#

if its just time based

#

what you mean

shell grove
fresh salmon
#

I think you're limited by Unity here, as everything is synced to the framerate, or the fixed time step, nowhere near fast enough to achieve what you want

frozen imp
#

You can't execute something faster than your program can run

dusty shell
#

im not really sure what you want to achieve

#

do you want to measure the elapsed time?

fresh salmon
#

And 1 / 44000 is quite fast

shell grove
#

The problem is that I want to stop the playback of an AudioClip at any given time. But stopping an AudioClip when it's not on a 0 sample will result in an audible "pop" sound

frozen imp
#

Which format are you using?

shell grove
#

AudioClips generated at runtime

#

so uncompressed wave?

#

I actually don't know what format they are

#
        //Generate Sine
        for (int j = 0; j < notes.Length; j++)
        {
            float[] samples = new float[(int) (44000 / notes[j].Frequency)];
            for (int i = 0; i < samples.Length; i++)
                samples[i] = Mathf.Sin(Mathf.PI * 2 * i * notes[j].Frequency / 44000);
            AudioClip ac = AudioClip.Create(string.Format("Sine {0}", notes[j].Name), samples.Length, 1, 44000, false);
            ac.SetData(samples, 0);
            sineClips.Add(ac);
        }
frozen imp
#

You can sample the timing and stop before that happens earlier in execution order probably instead.

shell grove
#

Could you elaborate?

flint sage
#

OS based timers do not have the precision to stop at 1/44000th intervals

dusty shell
#

basically you'll have to work with your clock speed

#

you cant realistically measure samples/time faster than you cycle trough your lines

frozen imp
dusty shell
#

only to use better hardware/write better code is what you can do

flint sage
#

Tbh, a quick fade out would probably work just fine

dusty shell
#

but you dont need to either

frozen imp
dusty shell
#

human reaction time is about 15-30ms

fresh salmon
#

Or when you pause, wait for the next "0 sample" as you call them, and stop there

shell grove
#

Hrmm. General question to understand the timing between operations.

var test = 1;
test++;
Debug.Log(test);

How long does it take to execute this code?

dusty shell
#

ask ur hardware

#

compiler

#

OS

#

it varies

fresh salmon
#

Three instructions in IL, with Debug.Log the most expensive one

shell grove
#

So is it tied to the clock of the CPU

fresh salmon
#

Yes

dusty shell
#

for example u have 1 core

fresh salmon
#

The exact timing cannot be precisely determined, as it depends on your CPU

shell grove
#

But something like

yield return null;

Is tied to the framerate?

dusty shell
#

this core now executes the OS, discord, steam, 300gb of internet services and your program

#

compared to only OS and ur program

#

the second runs faster

fresh salmon
dusty shell
#

he asked how to determine the speed at which instructions are executed

fresh salmon
#

Plus, CPU speed vary now, it can throttle down if it has nothing consequent to do

dusty shell
#

im explaining

#

that there are thousands of factors

shell grove
#

I see

dusty shell
#

also if the cpu overheats itll turn its clock down

#

so there is neither a way to determine how fast your program runs

shell grove
#

So even when the timing may be accurate on my PC, it might not be accurate on other peoples PC.

dusty shell
#

nor to pinlock it at an exact speed

#

exactly

frozen imp
#

@shell grove All you need to know is everything happens in one frame, and what you can manage is when in the frame it will happen.

fresh salmon
#

The main thing is, you'll never get a program to run as fast as your CPU clock, as most C# calls result in 1+ instructions

shell grove
#

So it would be better to make every timing frame-dependent to ensure accurate timing regardless of hardware limitations?

fresh salmon
#

So 1+ clock cycles

dusty shell
#

what you can do to improve performance for time critical tasks is to start a new thread on a new physical core and dedicate this thread to that very one task

#

make it async

#

and communicate with the main thread via an interface

frozen imp
#

frame independent that is

dusty shell
shell grove
#

But I thought frame independent meant that it's up to the hardware

dusty shell
#

but keep in mind that incorrect thread handling might actually turn your processing speed down

#

unity, c# and c++ based dlls all can offer multithreading solutions if youd want that

frozen imp
#

You can't know at which frame rate different hardware will run the program. You can force it though to lower rate.

#

But it's not recommended

#

Only universal factor is timing

shell grove
#

I think Timinator said that deltaTime could work

dusty shell
#

you basically just store the time

#

add the elapsed time to that each frame or tick

#

and compare it to your wanted threshold

#

if it exeeds you execute your whatever and reset the timer

frozen imp
#

What exactly do you want to do?

shell grove
#
var i = time.deltaTime;
yield return null;
Debug.Log(time.deltaTime - i);

I guess this would give me the time it took for that 1 frame to pass with yield return null;

dusty shell
fresh salmon
dusty shell
#

just speaking generally btw, unity caps the fps and thus game ticks to the monitors refresh rate right?

fresh salmon
#

Only if you tell it to, or have vsync enabled

dusty shell
#

yea

#

so

#

basically thats to be taken into consideration too

shell grove
#

I thought about an Idea, tho it may be a stupid one
Instead of

yield return new WaitUntil(() => Master.time / ((int) (44000 / notes[btn].Frequency) / 44000f / (int) (44000 / notes[btn].Frequency)) == 0f );

I could do

while(Master.time / ((int) (44000 / notes[btn].Frequency) / 44000f / (int) (44000 / notes[btn].Frequency)) != 0f)
{}
dusty shell
#

i spent a great deal of time

#

asking myself

#

how do i prevent cheaters from ramping up their clock speed to cheat speed walking

#

the simple answer is delta timing

shell grove
#

Tho I think that would freeze the program

dusty shell
#

but this applies universally

dusty shell
fresh salmon
#

Huh?

dusty shell
#

super old games suffer from this vulnerability

shell grove
#

No I meant the while loop xD

#

Sorry

dusty shell
shell grove
#

Sadly not, most of the time the samples take 2-3 seconds to stop

fresh salmon
#

Much more, like 16ms at 60fps

#

Because WaitUntil is tied to framerate, and is of course, variable

dusty shell
#

also id refrain from while loops in the main thread of unity

#

it freezes your entire game

shell grove
#

Basically every 16ms we got a shot that maybe we are on a 0 sample, if not we wait again

dusty shell
#

so

#

we talk about aprox 16ms inaccuracy?

#

that right?

shell grove
#

16ms in 44000hz is quite the amount of samples

dusty shell
#

then multithread it

#

and let the thread run async

#

only way i see in the unity env to get it run faster

shell grove
#

I never multithreaded

dusty shell
#

🤷‍♀️

#

its actually not that hard

fresh salmon
#

And I don't think it would be appropriate here

dusty shell
#

and both unity and .NET offer solutions

frozen imp
dusty shell
#

cuz i at least cant think of a way to measure the time faster(at higher frequency)

fresh salmon
#

Even if they multithreaded, it would be far too fast compared to the 44kHz rate the sound imposes

dusty shell
#

well and u have to consider weaker hardware too

#

welp i havent done much with audio playing yet so im mostly out then

unreal badger
#

yo guys, i wanna ask something, so i make a basketball game then the player can throws the ball when pressed left mouse, but the problem is when i click pause button the player can still throws the ball, so how can i fixed that?

fresh salmon
#

Is that question really suited for that channel, or did you post here because it's active?

#

Prioritize relevance over activity, folks

shell grove
#
if(paused)
return;

Add that in your ThrowBall function, or any equivalence to that.

#

I think I will try the FadeOut Solution since getting really accurate timings when dealing with this kind of frequency seems near impossible

#

Or, big brain moment

#

I could add a few 0 samples between each cycle of the sine. That way the WaitUntil could maybe catch it better?

#

Anyway big thanks for the help Timinator, SPR2 and Fogsight 👍

thick thorn
#

Is it possible to write a property drawer for a custom list class (which would basically just be a wrapper for list<T>) that draws the serialized fields for the most derived type of T? Perhaps through reflection?

shell grove
#

I sadly have no clue what a property drawer is Hambones. But I think some will know 👍 Good luck on your project

unreal badger
thick thorn
#

Basically I want a polymorphic container that allows you to edit derived types of T in the inspector. I think this is possible at least through reflection, possibly even not, but I’m not sure.

#

I think that in order to actually allow selection of a subtype in the inspector, reflection would be needed…

dusty shell
#

ive seen many talk about the old and new input system of unity

#

whats the actual technical difference?

thick thorn
#

Basically the new system provides the concept of actions, which lets you separate obtaining inputs from employing them.

shell grove
#

oh btw Timinator, I'm limited to C#4 and Unity 2017

#

Because I'm modding for a game that runs on that version. Dunno if Multithreading would even work there

thick thorn
#

Multi threading is very old

normal cedar
#

Hey anyone familiar with an issue where i cant make any kind of webrequest without a WEBGL build crashing on me

#

Maximum call stack size exceeded

#
using LitJson;
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class SaveFile : MonoBehaviour
{
    [Tooltip("Details from where to get the personalID")]
    public LoginDetails Login;

    public DataTable Data;
    [SerializeField] private string JSONLink;
    public JsonData jsonvale;

    public void Start()
    {
        Init();
    }

    public void Init()
    {
        StartCoroutine(Getlink());
        GetAchievements();
    }

    public IEnumerator Getlink()
    {
        UnityWebRequest client = UnityWebRequest.Get(Login.URL);
        client.SetRequestHeader("AUTHORIZATION", Login.Authenticate());
        yield return client.SendWebRequest();
        if (client.result == UnityWebRequest.Result.Success)
        {
            JSONLink = client.downloadHandler.text;
            Debug.Log(JSONLink);
        }
        else
        {
            Debug.Log("Could not make a connection");
            yield return null;
        }
            if (JSONLink.Length > 0)
            {
                jsonvale = JsonMapper.ToObject(JSONLink);
                Data.isLoggedIn = (bool)jsonvale["loggedIn"];
            }
    }

    public void GetAchievements()
    {
        if (Data.isLoggedIn)
        {
            Debug.Log("Nice");
        }
    }
}

[System.Serializable]
public class DataTable
{
    public bool isLoggedIn;
}

[System.Serializable]
public class LoginDetails
{
    public string URL;
    public string UserName;
    public string PassWord;

    public string Authenticate()
    {
        string auth = UserName + ":" + PassWord;
        auth = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth));
        auth = "Basic " + auth;
        return auth;
    }
}
shell grove
#

If you reach the maximum call stack you have an infinite loop somewhere

normal cedar
#

this is the only script active

#

and it doesnt have a loop

#

wait. i just uploaded an empty build and it still does it. let me check

unkempt nova
#

I'm trying to figure out the cause of an android build crash, so I installed Unity's Android Logcat package. I think I found the cause, but have no idea what I'm looking at. Anyone able to give any insight?

shell grove
#

@normal cedar
Maximum call stack size exceeded means that somewhere in your code, you are calling a function which in turn calls another function and so forth, until you hit the call stack limit.

unkempt nova
#

The server backend is written in Java, and this mentions a null pointer dereference, and seems to say it's a Java error, but that's all I've got. If I can just confirm that's the cause, that'd be good, but will need more info on which bit of code is causing it if possible

shell grove
normal cedar
#

chrome doesnt give me the error so it is opera being annoying now

unkempt nova
normal cedar
#

webgl has been nothing but a pain in the ass for me

shell grove
#

Well the backtrace shows it's mostly Unity

shell grove
normal cedar
#

it doesnt even get at that point

#

cant even start the game

shell grove
#

like GetAchievements(); or StartCoroutine(GetLink());

normal cedar
#

ill try that.

#

too bad it takes 10 minutes every single time to build

shell grove
#

Can't you run it in Unity?

normal cedar
#

in unity it runs fine

#

it only breaks on build

#

and when i put it on a server

#

and i need to it to load in a personalID to load in all their data

#

so it is too important

#

it works now

#

problem was Opera

shell grove
#

Weird

fresh salmon
unkempt nova
#

Hrm, ok. Thanks

thick thorn
#

well... just learned something new... [SerializeReference] will polymophically serialize objects.

#

Now I just need to figure out how to write the custom inspector to allow selection of a desired derived type when adding an element. That will probably require reflection.

#

Don’t mind me, im just talking to myself I guess…

fresh salmon
#

If you need a confirmation, Reflection can do that. Look for the Type:IsAssignableFrom(Type) method

#

Works with interfaces as well.
Classes only, Type:IsSubclassOf(Type) will do

thick thorn
#

Thanks. I think I probably also need to figure out how to create a aerialized object in a custom inspector, so that upon receiving a selection of a type, the aetialized object of the appropriate type is created.

fresh salmon
#

As long as the type can be instantiated (not abstract nor static nor interface), you can use Activator.CreateInstance(Type) to create an instance of an object at runtime

#

I think the object needs to declare a paramless constructor, unless there is an overload where you can pass arguments

thick thorn
#

i keep looking to the asset store for neat tools like this but usually can't find anything. looks like a lot of these types of things are just on github or whatever

white zephyr
#

Not exactly sure if this is the right channel: Does anyone have experience with debugging Unity crashes on Linux?

#

I have a coredump, but I don't know how to get the right stacktrace out of it, as GDB is unable to deal with the managed symbols from mono

thick thorn
#

oh wow you can make a property drawer apply to a field using an attribute... how did i miss that one... i feel like no matter how much unity i learn, i always feel like i know maybe 5% of it. the more i find out, the more i realize i don't know

unkempt nova
#

For my crash issue, I found the "tombstone" logcat was refering to. Any ideas what I can check for this? Looks like URP stuff, but this is basically gibbrish to me managed backtrace: #00 (wrapper managed-to-native) UnityEngine.Rendering.ScriptableRenderContext:Submit_Internal_Injected (UnityEngine.Rendering.ScriptableRenderContext&) #01 UnityEngine.Rendering.ScriptableRenderContext:Submit_Internal () <0x13> #02 UnityEngine.Rendering.ScriptableRenderContext:Submit () <0x13> #03 UnityEngine.Rendering.Universal.UniversalRenderPipeline:RenderSingleCamera (UnityEngine.Rendering.ScriptableRenderContext,UnityEngine.Rendering.Universal.CameraData,bool) <0x80b> #04 UnityEngine.Rendering.Universal.UniversalRenderPipeline:RenderCameraStack (UnityEngine.Rendering.ScriptableRenderContext,UnityEngine.Camera) <0xbbf> #05 UnityEngine.Rendering.Universal.UniversalRenderPipeline:Render (UnityEngine.Rendering.ScriptableRenderContext,UnityEngine.Camera[]) <0x157> #06 UnityEngine.Rendering.RenderPipeline:InternalRender (UnityEngine.Rendering.ScriptableRenderContext,UnityEngine.Camera[]) <0x3f> #07 UnityEngine.Rendering.RenderPipelineManager:DoRenderLoop_Internal (UnityEngine.Rendering.RenderPipelineAsset,intptr,System.Collections.Generic.List`1<UnityEngine.Camera/RenderRequest>) <0xcb> #08 (wrapper runtime-invoke) <Module>:runtime_invoke_void_object_intptr_object (object,intptr,intptr,intptr)

#

Looks like the same info as was in my screenshot. Also, I was trying to track down some mobile performance issues with profiler and I'm pretty sure these calls were at the top. I'm thinking they're related, what do you think?

#

Unity 2021.3.14f1, URP version 10.5.1 btw

#

Letting the game start in portrait mode, it seems ok (sometimes...), but soon as I turn the phone so it switches to landscape, it seems to crash. Not sure if it's just randomly crashing and it just seems like the orientation is related though Yeah I think it's just random

stuck onyx
#
             transform.position = Vector3.Lerp(startPosition, target, t);```
I'm using this inside of a coroutine but sometimes the timeToReachTarget varies significantly (0.2 -0.3 sec).... I suspected it was because the change on the frame rate and changed Time.deltaTime for Time.fixedUnscaledTime....  now just varies 0.01 - 0.02.   Does it make sense?
sly grove
stuck onyx
#

@sly grove yes thats how is done

#

its set to 1

sly grove
#

Ok so what are you asking

#

you said "timeToReachTarget varies significantly"

stuck onyx
#

but when i was using normal deltaTime

#

i measured that time

#

and was not exactly 1 dependinng when did i launcched the method

sly grove
#

Can you show a little more context? How is your loop structured and what kind of yields are you using etc

humble onyx
stuck onyx
#

sure , 1 second

sly grove
#

It will never be exactly 1 second btw, there will always be an error of up to however long a single frame takes for your game.

stuck onyx
#
   private IEnumerator MyCoroutine()
    {
        float duration = 1;
        float lerp = 0;
     
        while(duration>0 && lerp<1)
        {
            lerp += Time.fixedUnscaledDeltaTime/duration;
            sceneFader.alpha = Mathf.Lerp(1,0,lerp);
 
            yield return null;
        }

    }
#

yeah but the difference sometimes was more than 0.2 seconds

#

i suspected it was beccause sometimes i call it when there is a framedrp

#

framedrop*

#

thats why i changed

#

Time.deltaTime TO Time.fixedUnscaledDeltaTime

#

now seems to be always same time...

#

I'm asking if what I did makes sense

sly grove
#

why are you using fixedUnscaledDeltaTime

#

it should be unscaledDeltaTime

stuck onyx
#

because i've heard deltaTime is frameDependant and i thought that could solve it

#

aha

#

so with unscaledDeltaTime i would have the same result than now

sly grove
#

no... deltaTime is there to fix framerate dependency

#

since your coroutine is looping every 1 frame, you need deltaTime to adjust for that

stuck onyx
#

but if I use deltaTime the times varies between 0.2 or even 0.3 seconds , i dont understand why

#

i used StopWatch class to measure it

sly grove
#

print out the current time and the value of lerp every loop.

#

therre's no magic here

#

it will stop when lerp reaches 1

humble onyx
#

deltaTime is the time since the last frame
if your frame time / FPS varys so does deltaTime ands thats wht its for

stuck onyx
#

corrrect?

sly grove
#

if your game is chugging along such that a frame takes 0.2 seconds to render, there can be an error of up to that much time

#

Are you having framerate issues?

stuck onyx
#

yes, actually i do some sorrt of render heavy stuff in one ocasion

#

no, just on that particular moment

#

ill put some context

sly grove
#

If you have a particularly slow frame, then yes, this can have an error of up to the length of time it takes to render that one frame

stuck onyx
#

aha, so the correct one to avoid this would be the one you suggested?

#

unscaledTime?

sly grove
#

No, there's no avoiding it

stuck onyx
#

or the one im using (which seems to work)

sly grove
#

The answer is to fix your framerate problem

thick thorn
stuck onyx
#

yes, the one im using makes it work

#

@sly grove ill put more context

#

im doing this:
-1 I fade the screen white with the coroutine (no prob)
-2 I ennable a camera and take a render snap to create a texture (this takes some time depending on the device)
-3 whenn the snap is done... i fade to transparent again

#

1st fade takes 1.000 second, 3rd fade takes 0.6 - 0.8 seconds

#

I think its because, even if i do it AFTER the render snap is done there still might be some work going on

#

this happened using Time.deltaTime

#

then i changed to Time.fixedUnscaledDeltaTime and 1st and 3rd fades take the same amount of time... just with 0.0X difference

#

and I'm asking.... does this make sense?

#

😄

sly grove
#

I think you're just seeing the cumulated effects of error between all three coroutines

#

Your first one might take like 1.05 seconds
The second one 1.07 seconds
the third one 1.04 seconds

So the whole process takes 3.16 seconds

#

just as an example

stuck onyx
#

uhmm the first one and third one are the same code... and i do

    sw.Start();
 while(duration>0 && lerp<1)
        {
            lerp += Time.fixedUnscaledDeltaTime/duration;
            sceneFader.alpha = Mathf.Lerp(start,end,lerp);
 
            yield return null;
        }
Debug.Log("SatviewExit Time " +enable+" :"   +sw.ElapsedMilliseconds);
        // sw.Stop();
#

so i can see pretty clear the times of the first and third coroutine

#

take into account the second doesnt startt until first is done

#

and 3rd doesnt start until second is done

sly grove
#

Note that Unity's time API deals with the time as it was at the beginning of the frame always.

stuck onyx
#

im measurinng the times of 1st and 3rd by separated

sly grove
#

If Time.time is 492.3 for example, it will be 492.3 for the entire frame. Unlike System time apis which will keep ticking even during a frame

stuck onyx
#

and what does that mean? sorry i didnt get it 😅

sly grove
#

It means that there will be some discrpancies between what you see with things like Stopwatch and what Unity's time APIs are reporting

stuck onyx
#

oh

#

so deltaTime should take the same amount of time then.

#

gonna try again.

sly grove
#

Could you show all your code btw and what is being printed?

stuck onyx
#

sure

#

how was the color paste thinng?

#
public void TriggerSatViewExitFader(bool enable, Action onCompleted)
    {
        StartCoroutine(SatviewExitFaderCoroutine(enable,onCompleted));
    }
    private IEnumerator SatviewExitFaderCoroutine(bool enable,Action onCompleted)
    {
        float duration = enable
            ? configService.varsCfg.satViewExitFadeInTime
            : configService.varsCfg.satViewExitFadeOutTime;
        float start = enable ? 0 : 1;
        float end = enable ? 1 : 0;
        sceneFader.gameObject.SetActive(true);
        float lerp = 0;
        Stopwatch sw = new Stopwatch();
        sw.Start();
        while(duration>0 && lerp<1)
        {
            lerp += Time.fixedUnscaledDeltaTime/duration;
            sceneFader.alpha = Mathf.Lerp(start,end,lerp);
 
            yield return null;
        }
        Debug.Log("SatviewExit Time " +enable+" :"   +sw.ElapsedMilliseconds);
        sw.Stop();
        sceneFader.alpha = end;
        sceneFader.gameObject.SetActive(enable);
        onCompleted?.Invoke();
    }```
#

there

#

if i pass enable=true fadesInn if i pass enable=false fadesOut

sly grove
#

ok makes sesne

#

(other than fixedUnscaledDeltaTime)

#

and what does it print

stuck onyx
#

first i noticed visually it was not totally exact (using deltaTime)

#

then i placed the StopWatch and confirmed

#

ill runn, 1 sec

#

@sly grove this is with fixedUnscaledDeltaTime:
[Log] SatviewEnter Time True :862
[Log] SatviewEnter Time False :969

#

first linne fadeIn second fadeOut

#

acceptable

#

now i try deltaTime

sly grove
#

SatviewEnter Time doesn't the code say SatviewExit Time?

stuck onyx
#

yeah i just took the method below but its the same code actually, didnt feel like merging both

#

its the same code but taking different fadeTimes

sly grove
#

Btw does your game mess with Time.timeScale at all

stuck onyx
#

but all are 1 currenntly

#

no,

#

never

sly grove
#

ok what do you get when you do deltaTime

stuck onyx
#

runnin

#

[Log] SatviewEnter Time True :1015
[Log] SatviewEnter Time False :696

sly grove
#

🤔

stuck onyx
#

0.3

sly grove
#

the first one makes sense

stuck onyx
#

for a coder is nothing but for my game designer its a lot 😅

sly grove
#

the second one... doesn't

#

you 100% sure the code is the same?

stuck onyx
#

well, for a coder, in my context

#

yes, 100%, i paste againn

#

i paste the correct

#
private IEnumerator SatviewEnterFaderCoroutine(bool enable,Action onCompleted)
    {
        float duration = enable
            ? configService.varsCfg.satViewEnterFadeInTime
            : configService.varsCfg.satViewEnterFadeOutTime;
        float start = enable ? 0 : 1;
        float end = enable ? 1 : 0;
        sceneFader.gameObject.SetActive(true);
        float lerp = 0;
        Stopwatch sw = new Stopwatch();
        sw.Start();
        while(duration>0 && lerp<1)
        {
            lerp += Time.deltaTime/duration;
            sceneFader.alpha = Mathf.Lerp(start,end,lerp);
 
            yield return null;
        }
        Debug.Log("SatviewEnter Time " +enable+" :"   +sw.ElapsedMilliseconds);
        sw.Stop();
        sceneFader.alpha = end;
        sceneFader.gameObject.SetActive(enable);
        onCompleted?.Invoke();
    }
sly grove
#

Can you print out what the duration is?

        float duration = enable
            ? configService.varsCfg.satViewEnterFadeInTime
            : configService.varsCfg.satViewEnterFadeOutTime;```
I See you're getting two different durations
stuck onyx
#

duration is always 1 , 100%

sly grove
#

Print it

stuck onyx
#

but i can print

sly grove
#

just to make sure

upper scarab
#

I have an Assembly Definition Question!

My folder structure looks like:

Assets

  • Game1
  • Game2
  • Plugins
  • Common

So, each of the folders above has an asmdef. All of the asmdefs rely on "Plugins".

I have TextMeshPro as a reference in Plugins. What's curious is that even though Game1, Game2, and Hub rely on plugins, they can't seem to find the reference for TMP. Is there a simple setting I'm missing? It feels overkill to have to add TMP as a hard reference in every assembly.

stuck onyx
#

running...

#

Duration: 1
SatviewEnter Time True :1002

Duration: 1
SatviewEnter Time False :741

sly grove
#

I don't understand how lerp could be getting > 1 then

stuck onyx
#

what is taking > 1 is the time but not the lerp result

#

you mean the alpha?

sly grove
#

I mean the lerp variable

#

that loop continues as long as lerp is < 1

#

If you're adding deltaTime each frame (divided by 1 which doesnt matter), that should take 1 second (or slightly longer)

#

as it does for the first run

#

Unless timeScale is getting affected

stuck onyx
#

oh!

sly grove
#

Can you search your project for Time.timeScale?

stuck onyx
#

yeah, notim eht whole proyect, just comparsions

#

not in the whole project

sly grove
#

What happens if you use Time.unscaledDeltaTime

stuck onyx
#

let me try

upper scarab
#

did you use control+f or control+shift+f to search the project?

stuck onyx
#

but thats the default so its alright

stuck onyx
#

but i use Rider

sly grove
#

That only searches one file, no?

stuck onyx
#

sorry, command + Shift + F

sly grove
#

Regardless, if unscaledDeltaTime works then we know it's a time scale issue

upper scarab
stuck onyx
#

Duration: 1
SatviewEnter Time True :1022
Duration: 1
SatviewEnter Time False :152

#

this was even worse 😮

sly grove
#

wtf

stuck onyx
#

yeah, did it again

#

same

#

144

sly grove
#

that makes... so little sense lol

stuck onyx
#

ill try fixedDeltaTime

#

[Log] Duration: 1
[Log] SatviewEnter Time True :872

[Log] Duration: 1
[Log] SatviewEnter Time False :1068

#

hmmmmmmm

#

nnot as good as ffixedUnscaledDeltaTime

#

why the heck is happenning this

#

with fixedUnscaledDeltaTime i get it almost the same

#

it has to be something related with the camera.render() im calling

sly grove
#

What happens if you print out Time.time before and after the loop

#

instead of using StopWatch

stuck onyx
#

ok 1 second

#

look

#

if i use the same method

#

but without the camera.Render() between them

#

Time.deltaTime works fine

sly grove
#

oh there's a Camera.Render happening?

stuck onyx
#

of course its the second step i told you

sly grove
#

how come

stuck onyx
#

thats why i said the framedrop thing

sly grove
#

Ohh

stuck onyx
#

-1 I fade the screen white with the coroutine (no prob)
-2 I ennable a camera and take a render snap to create a texture (this takes some time depending on the device)
-3 whenn the snap is done... i fade to transparent again

sly grove
#

ok - I wonder if there's a bug with Camera.render where unity doesn't account for the time that takes appropraitely

stuck onyx
#

if step 2 is out of the equation then works fine

sly grove
#

can you see if you wait like 1 extra frame between step 2 and 3

stuck onyx
#

sure

sly grove
#

like add a yield return null at the beginning of the coroutine or something to do it quickly

stuck onyx
#

but then the time will be affected

#

or not

#

ah okk ok

#

SatviewEnter Duration: 1
SatviewEnter Time True :1021
SatviewEnter Duration: 1
SatviewEnter Time False :700

#

same

sly grove
#

I don't ujderstand T_T

#

can you show your camera render code

stuck onyx
#

sure

#
  void Awake()
    {
        if (snapCam.targetTexture == null)
        {
            snapCam.targetTexture = new RenderTexture(resWidth, resHeight, 24);
        }
        else
        {
            resWidth = snapCam.targetTexture.width;
            resHeight = snapCam.targetTexture.height;
        }
    }
    
    public void SetWaterObject(GameObject waterGO)
    {
        waterObject = waterGO;
    }

    public void TakeSnapshot(Action onCompleted)
    {
        waterObject.SetActive(false);
        waterSprite.enabled = true;
        snapCam.enabled = true;
        snapCam.Render();
        snapCam.enabled = false;
        waterObject.SetActive(true);
        waterSprite.enabled = false;
        onCompleted.Invoke();
    }
#

gotta go now @sly grove thanks a lot for your help, if you come up with something please let me know

undone coral
#

like a reflection effect for sprites?

#

i think there's a lot about this online

#

usually you have to make sure the camera renders at the "right time", and then the most performant way to use the render texture is through a shader property that isn't exposed in the shader graph

#

you can make 2d sprite shader graphs in URP

#

@stuck onyx

undone coral
undone coral
upper scarab
undone coral
#

what is the underlying issue?

#

you're saying 27 folders with asmdefs in them, each with 27 scenes, that you build to 27 distinct exes?

#

you can just reference it once in common

upper scarab
#

The underlying issue is that we licensed several games to our platform. They each used their own version of TMP when they were made. We wanted to unify them all to use the Package Managed version of TMP

undone coral
#

you should be able to reference it once in common

upper scarab
#

So "plugins" is our "common"... and all of the games reference plugins. You're saying that if Plugins references TMP, then the rest should have access? That was my thought as well, but that doesn't seem to be the case

undone coral
unkempt nova
upper scarab
# undone coral what kind of error do you see?

So in this case, the scripts are in Assets/Hub

the Hub.asmdef, relies on plugins.asmdef. plugins.asmdef references TMP. I was hoping that the scripts in Hub could use TMP, without adding a reference to TMP in the hub.asmdef

static marsh
upper scarab
static marsh
upper scarab
crystal ridge
#

If I have an abstract base class called Food and it implements an interface called IFood, does that mean when I create a new script and inherit from Food it also inherits the interface (IFood) as well?

#

the reason is, because I have a trigger looking for the interface

IFood food = other.transform.getcomponent<IFood>();

But i'm wondering if I even NEED that, or I can just look for the base class instead from the derived script

Food food = other.transform.getcomponent<Food>();
sly grove
#

If you have Food : IFood and HotDog : Food then implicitly it is true that HotDog : IFood

crystal ridge
#

Thanks @sly grove! I think you're like 5/5 of my questions answered lol, I need to buy you a coffee sometime

polar ermine
#

i have a scriptable object class Statuses that acts mostly as a dictionary to hold objects of a serializable class Status in an array. I'm able to add and remove statuses in the inspector very easily. Now I'd like to be able to reference these statuses elsewhere in the inspectors of other gameobjects, somehow.

example being i have an enemy type as their own scriptable object. I'd like to have a list of "statuses" in that script, and I'd like to simply pick and choose which status that enemy will have in the inspector from said list that i filled out in the original Statuses SO.

#
public class Statuses : ScriptableObject
{
    public List<Status> statuses;
}

this is the whole class; i basically want to use whatever's in the statuses list as a dropdown to select from. it's probably simpler than i think but im not familiar enough with unity 😔

normal cedar
#

@polar ermine It would just be better to call the status script in your enemy as a variable

#

if you have to select it it shows you the statusses anyway

#
public class Enemy : MonoBehaviour
{
  public Status status;
}

#

but if you wanna go real fancy it is possible but the solution i showed above is just way cleaner

polar ermine
#

The only problem with that is i need to input the values for that particular Status object all over again

#

i write it once in the dictionary and need to write it again it kinda defeats the purpose of a dictionary

normal cedar
#

wait wut?

#

you know scriptableobjects can not save contents that have been changed during runtime right?

#

you have to pre-assign them.

polar ermine
#

im pretty sure i've accidentally permanently mutated values in a SO from in game but that's not what im trynna say, i think

normal cedar
#

that would be odd but possible if you have a save loading system.

But what would be better is to do this:

[CreateAssetMenu("idk what goes here anymore")]
public class Status : ScriptableObject
{
  Data
}

and then have a seperate class for your enemy where you just call status

public class Enemy : MonoBehaviour
{
  public Status status;
}

sly grove
normal cedar
#

that was it yeah!

polar ermine
#

i see, good to know

normal cedar
#

if you have any question about how it goes in working i could show you

polar ermine
#

im just trynna think if my current set up could work

#
[Serializable]
public class Status
{
    public string name;
    public string description;
    public Sprite sprite;
}

this is my current status class, and i showed the statuses dictionary SO class earlier

normal cedar
#

oooh yeah it is very possible

#

you can just make it into a CreateAssetMenu

polar ermine
#

right. in my enemy class i started by doing Status[] statuses, but in the inspector i have to fill all that information again, i can't pick from the list of statuses i already made.

#

i guess making each Status it's own thing would be good too, though

#

and assign each status to a list object in the dictionary so?

normal cedar
#

yes

#

very possible

polar ermine
#

makes it a little bit less modular than I'd like, but I'll give it a shot

normal cedar
#

ofcourse what you could do it make it like you want, then have an enum with all the statusses name and then do a for loop

polar ermine
#

right. and link each status with the associated enum at runtime and just use that. i started doing that but started to wonder if i could just simply use a list of statuses in place of an enum

#

because i'd need to be sure i had a good system of "linking" that would involve a standardized naming scheme or something, which is good practice but prone to error because im dumb

#

that said, I did get something to work to some effect of how i wanted it to.
i just worry about scalability and how much work I'll have to do in the long run using one solution over the other.

#

might be minor, but needing to make a scriptable object for each status, and putting that object in the statuses dictionary once and then also adding them to cards that use that status instead of being able to directly link to the dictionary feels inefficient to me.

viral flame
#

I know I can timeslice it, but it still feels wonky that simply sorting some lists consisting of not many things is so slow.

thick thorn
#

well are you running this on each ai dude?

#

if so, maybe it has to do with how many times you're doing the for loop on lines 53-67

viral flame
#

Yeah, I mean 80 * 16 = 1280 but that doesn't seem like thaat many raycast calls, and if I remove the sorting, it takes ~1ms (total time for all 1280) to do that.

thick thorn
#

a lot less gc without sorting?

viral flame
#

That makes total sense yeah, but no idea why the sort is exploding.

#

If I have the sort in, the profiler is telling me between 8ms/12ms per frame for this func (and 10/20KB of GC), without it, no GC and ~1ms. 😦

#

So it's 100% the sorting, but I feel like there must be something obvious I'm missing or etc, it shouldn't take that long to sort a max of 16 things.

thick thorn
#

looks like using an IComparer causes per-frame allocations

#

maybe convert your class to just a static func, as stated in here?

#

dunno

#

or i guess implement your own sort algorithm. shrug.

#

not the nicest answer i guess

#

your compare looks like a pure function, so should be easy to convert to a static func

#

or you could even use an anonymous method i guess

#

(is that the same as a static func?)

viral flame
#

An anonymous method I believe will cause some GC since it must capture surrounding context for the lambda

thick thorn
#

ahh

viral flame
#

Yeah I looked at the non gc list thing you linked earlier, and tried many diff methods, and they all still cause GC, I dunno lol.

thick thorn
#

shrug.

#

sry

viral flame
#

It's good, thanks for the help. I did manage to get it a bit faster by hinting compiler to inline the comparer, i.e.

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int Compare(Transform x, Transform y) {
      var xdist = (x.position - _me.position).sqrMagnitude;
      var ydist = (y.position - _me.position).sqrMagnitude;

      return xdist.CompareTo(ydist);
    }
#

So that's cool, I guess, now it's like ~5ms on avg.

thick thorn
#

nice

viral flame
#

I ended up removing the sort, and just searching for the closest in the list when a function is called, ended up being much faster, and will refactor later if required. 😛

undone coral
#

it looks like you figured it out

#

what were you trying to do?

#

this kind of spatial querying is expensive

#

you might want to use a dedicated thing

undone coral
undone coral
#
public class CardGame : ScriptableObject {
 [SerializeField] private Status[] m_Statuses;
 [SerializeField] private Card[] m_Cards;
 ...
 public Status[] statuses => m_Statuses;
 // or??
 public Status GetStatus(StatusEnum status) { ... }
}

@polar ermine

#

you only need one

#

do you see why this is less painful?

#

still works with the inspector

#

"but what if i have lots"

#

you don't right now

#

and even when you have more, it'll be less painful than having a ton of individual assets

#

that you will have to gather into an array anyway

polar ermine
#

yeah, i'd prefer not to have a SO for each status. it doesn't scale well i dont think
how does it work in the inspector exactly?

undone coral
#

you click on it

#

and then you hvae an array

#

etc. etc.

#

no custom editor necessary

#

anyway i think you'll figure it out

undone coral
#

it's saying it can't find TMPro

upper scarab
undone coral
#

if that works for you

upper scarab
#

yep that seems like the only solution!

undone coral
#

27 clicks... it'll take you 2 minutes

upper scarab
#

Im not worried about the time, moreover the fact that if we end up with other dependencies it makes connecting all of the wires more complicated 😅

It feels unclean is all lol

viral flame
# undone coral what were you trying to do?

Just create a list of nearby entities within the FOV not obstructed by obstacles.
It was 20KB per frame, which would end up being quite a bit over time IMO. (1.2MB / second, so after 10 mins, you're gonna have nearly 1GB of memory leak)

viral flame
#

With the switch to not sorting, and only searching on demand lowered the per frame time (for ~100 of them), from 5ms to like 0.2ms, so it's basically nothing now lol.

plucky laurel
#

from my experience overlap sphere even non alloc is slower than any conventional spatial structure

#

i had scenarios where 1000 units were querying in radius, at first i naively used overlap, then a simplest grid possible, and grid ran at 200 fps vs 20

#

now i use mix of grid and spatial hash, and i can go to 100k at 60 fps on a single thread, in a pure scenario without transforms

#

transforms are quite expensive

viral flame
#

Well, the overlap sphere itself wasn't the issue, it turned out to be the sorting which is weird, and at the radiuses I'm expecting to use, I'm not too worried about it (for now), though I may end up doing something smarter if required i.e. space binning or some quadtree, though I would assume they do that in the physics engine internally, but who knows

#

The raycast was the other expensive part, but I fixed that (mostly) by limiting it to the single hit, since ANY hit is "obstruction"

#

I should have SS the profiler, but again, something like 98% of the time was in the sort, which is wild, but ... .net strangeness I suppose

plucky laurel
#

you can cache the positions and ditch transforms

#

write your own sqrmag and other simple api calls (angle) with agressive inlining

#

should batch the whole thing tbh, at end of frame or some sync point, cache positions, update the buffers, next frame they have the info

viral flame
#

Yeah, it's fine for now with slight time slicing, can render 400+ npcs at 60fps, which is more than I'll ever need for the type of thing I'm doing. thanks for the advice though!

stuck onyx
#

@undone coral what i'm doing is to create a texture from all my city in 3D taking a capture, then i set that as texture to create a big map of all my city. I do that to create a satellite view, kid of a google maps if you like....

#

but the problem here is we dont know why the times of execution of a coroutine are so different using deltatime, unscaledDeltatime, and unscaledFixedDeltaTime

#
private IEnumerator SatviewEnterFaderCoroutine(bool enable,Action onCompleted)
    {
        float duration = enable
            ? configService.varsCfg.satViewEnterFadeInTime
            : configService.varsCfg.satViewEnterFadeOutTime;
        float start = enable ? 0 : 1;
        float end = enable ? 1 : 0;
        sceneFader.gameObject.SetActive(true);
        float lerp = 0;
        Stopwatch sw = new Stopwatch();
        sw.Start();
        while(duration>0 && lerp<1)
        {
            lerp += Time.deltaTime/duration;
            sceneFader.alpha = Mathf.Lerp(start,end,lerp);
 
            yield return null;
        }
        Debug.Log("SatviewEnter Time " +enable+" :"   +sw.ElapsedMilliseconds);
        sw.Stop();
        sceneFader.alpha = end;
        sceneFader.gameObject.SetActive(enable);
        onCompleted?.Invoke();
    }```
#

this is the coroutine....
the steps are

  1. Execute coroutine with enable=true (fades to white)
  2. Once is done i do the Camera.Render to create the texture
  3. Once is done i execute the coroutine step 1 with enable false (fades to trasparent)
#

step 1 and step 3 take different times if we use Time.deltaTime

#

a 0.3 sec difference approx

#

if we take step 2 out of the equation coroutine always take same amount of time of course

#

@sly grove was taking a look to this yesterday too and didnt find too much sese

#

sense

versed pewter
#

Hello, I am trying to do a HTTP post from C# into PHP.
I have used this example: https://www.php.net/manual/en/features.file-upload.post-method.php
And have successfully uploaded files on my website to my server.

If I try to send a json file with the C# WebClient, the response from the server is; "Possible file attack" or "Failed to open streams: permission denied".

I have tried to change the folder permissions trough a FTP client and trough Chmod but this still does not work.

Anyone here familiar with anything like what I am implementing?

cosmic basalt
#

use httpclient

#

who knows what that thing's doing

covert aurora
#

Hey

#

👋

versed pewter
plush lion
#

Hey, I'm trying to use the FreeImage external library in an Android build. It works fine on the editor, but when I build the dll goes missing and I get a dllNotFound exception through logcat.

I tried to force Unity to include it with a linker, the resources folder, and even tried to include it manually in the apk after the build (lmao), nothing worked. Anybody got an idea?

tough tulip
# stuck onyx if we take step 2 out of the equation coroutine always take same amount of time ...

Camera.render might take a very significant amount of time. And Unity works on time slicing. There's no way you can get a consistent timing. Delta Time is accumulated throughout the frame from start to end and is applied on the next frame at beginning.

From what I gather, something like this is happening at your end. It's just an example and are not at all representing the actual timings from your case.

Second last frame before loop ends:
value of lerp = 0.9 or something else behind 1. Throughout this frame, your Time.time remains same.

Last frame:
Suddenly your deltaTime has a large spike and crosses way above 1f. Say 1.2f which you see as the error in your measurement. It's totally fine and you can't avoid it.

Though I'm curious about the practical issues you are facing because of the unexpected error

long abyss
#

Hello, i've created a shader graph and I want to show it "fullscreen", how do i do that?

fresh salmon
long abyss
thick thorn
#

is anybody familiar with the performance implications of [SerializeReference]? I have a List<BaseClass> that I've annotated with [SerializeReference] and i notice that there is a significant slowdown in play mode when i have that list expanded, but the slowdown goes away when i unexpand the list.

#

when i had the underlying class viewed in the inspector without [SerializeReference], I didn't get the slowdowns, so it does seem to be that annotation

#

and the profiler shows that the massive slowdowns are definitely in the editor loop.

thick thorn
#

maybe this is more or an editor question...

undone coral
# stuck onyx sense

i feel like you have greatly overcomplicated this effect. also, camera.Render() is synchronous

undone coral
thick thorn
#

for performance reasons?

undone coral
#

try to solve your problem without it

#

no, just in general

thick thorn
#

why?

undone coral
#

it doesn't do what it advertises it does

thick thorn
#

can you explain further?

undone coral
#

it looks like it can solve problems like "lists of differently typed objects" but it can't

#

it does solve that problem, but very poorly

#

how many different subclasses of baseclass do you have?

thick thorn
#

right now just one

#

i'm just testing this out

undone coral
#

and how many do you think you will have?

thick thorn
#

maybe 4 or 5

undone coral
#

then the best thing to do is

[Serializable] class T {
 ...
}

class Container<T1, T2, T3>
  where T1 : T
  where T2 : T
  where T3 : T {
  [SerializeField] private List<T1> t1s;
  private List<T2> t2s;
  private List<T3> t3s;
  ...
  public IEnumerable<T> allTs() {
   return t1s.Concat(t2s).Concat(t3s);
  }
  ...
}

or, use odin

#

because the inspector just doesn't interact well with this sort of model

#

usually when you have a list of things that can be different types, you're doing something wrong anyway

#

so what if the types all have the same base class? it isn't as useful as it seems

#

because you tend to have very few subclasses

#

it makes sense when it's List<UIElements> and there may be hundreds of different UI elements

#

it makes less sense for gameplay stuff you're writing yourself, when invariably the number of subclasses is like, 1-5

#

i would recommend just using odin because i bet you are messing with serialize reference

#

for the purposes of getting the inspector to work and nothing else

thick thorn
#

yes that's correct

undone coral
#

SerializeReference is for something else entirely

#

so just use odin

thick thorn
#

what's it for?

undone coral
#

making it easier to get useful inspectors

#

without writing custom inspectors

thick thorn
#

isn't that what you said above?

undone coral
#

i'm saying odin gives you exactly what you want

thick thorn
#

oh i mean...

undone coral
#

an inspector for a list of subclass instances without having to write a custom editor

thick thorn
#

what's serializereference for?

viral schooner
#

I have a question. I am trying to destroy an object when it is hit by light, colliders are not working, and I do not want to raytrace every instance in the game, as these are enemies that multiply at respawn once destroyed.. any ideas?

undone coral
# thick thorn what's serializereference for?

it's for serializing objects when you don't know the type ahead of time. for example, if you're creating a Localization package and you have a class Localizable<T>, and you'd like to serialize an instance of something like X : Localizable<string> but at the time your code is written, you don't know that

thick thorn
#

ahh

#

well anyway the easiest solution here is probably make the objects derive from monobehaviour and just add each as a component to a gameobject

undone coral
#

people use it for "I would like to serialize an IBlah"

#

yes, that definitely works

#

but Odin is what you really want

#

which is a better inspector

thick thorn
#

i'll look into it. good deal now i guess

#

i've sort of known about it for a long time but never used it

#

mostly because i couldn't find a list of its capabilities

undone coral
#

is this a purpose built unity library?

thick thorn
#

i don't really understand your assertion that a list of base classes isn't useful. for example, i use it to polymorphically execute actions that other entities add into a queue. not sure how i'd do that without list<UnitAction>

undone coral
sage radish
thick thorn
#

2019 something. Guess I should upgrade…

#

Actually lemme check…

#

oh yeah it's 2020.3f.1f1

#

so i guess i'm upgrading

sage radish
#

I wish there was a place I could search through all Unity version changelogs. I'm trying to find mentions of SerializeReference in recent changelogs.

plush lion
undone coral
#

otherwise this will just fail

plush lion
#

Is this the reason it fails ? ^^"

undone coral
#

better question: why do you need freeimage?

#

what 1 image format are you trying to read

#

you would need to build freeimage specifically for android

#

which is straightforward but arcane

versed pewter
thick thorn
undone coral
#

you're doing everything fine

#

what i really mean is

regal olive
undone coral
regal olive
undone coral
#

unity's scene is data, it's not like, a piece of runnable c# code

#

it's not an instance of a class

#

they pretend the stuff you drag and drop into the inspector is instances of a class

#

it is clunky to turn polymorphic c# objects into data. you always wind up with a "type" field somewhere

#

SerializeReference ships that type field for you, but in a way that has surprising consequences

#

polymorphism makes the most sense when you're designing something that's meant to be extensible by other people, or has behavior that is unknowable

#

it's less useful when you're building a game, because you sort of know 100% what everything will do. the polymorphism turns into an organizational feature, not something essential to getting the code to work

#

concretely, what do you do with this advice?

#

usually when i want something to appear in the inspector without causing a huge headache, i make a struct and stuff all the aspects of it into there

regal olive
undone coral
#

for small numbers of types known ahead of time

#

so for example

#

like tell me what you are trying to store?

#

like enemies?

#

you want to describe enemies?

#

or something

thick thorn
#

it's basically a terrain tile type. or a terrain tile feature type

#

actually it's a controller for those things

thick thorn
#

it's kind of unfortunate that the unity inspector fights so hard with the basic nature of c#

plush lion
thick thorn
#

like c# has all these elegant solutiosn for problems but the inspector just says no

regal olive
# undone coral it can for sure. i think the thing i'm writing already exists in some library

The code referenced above looks a bit off. I probably don’t have a ton of context to say for sure, but you do! Just surfacing this as an opportunity to reevaluate the desired traits of the code you’re producing. If you kick the tires and find everything okay, that’s awesome!

For me, I try to look out for overly generic code as it’s a sign I’m conplexifying code, or trying to buy abstractions prematurely? Not trying to be a jerk or anything, just trying to help

regal olive
undone coral
#

did you try just using unitywebrequest to load images

#

Texture texture = ((DownloadHandlerTexture)uwr.downloadHandler).texture;

undone coral
#
class Map {
  public Tile[] tiles;
}
struct Tile {
  int type;
  // stuff that is common to
  // all tiles
  int elevation;
  // thing that is interpreted
  // differently by the tile
  // types. for example, maybe
  // value means the height of
  // a tree tile, or the depth
  // of an ocean tile, or the
  // number of berries on a 
  // berry tile
  int value;
}
#

you can still have

class GameTile {
  Tile tile;
}
class BerryTile : GameTile {
  int startingBerries => tile.value;
  int currentBerries {get; set;}
}
tough tulip
# plush lion I'm loading a shit ton of photos at once, and to not freeze the application I us...

The problem with a texture loading is that even if you create a texture on a different application you need to marshal that texture data from Free image library to Unity in the end.
UnityWebRequest handles texture very well in that aspect. I was able to load more than 200jpgs without any issue on mobile devices.

The main challenge comes when the texture is being uploaded to GPU. That has always been a bottleneck in engines because that upload process is synchronous and will stall your main thread. There are techniques to avoid it for ex texture streaming. It loads a texture in lower mips and then gradually raises up the mips. It's quite evident in most cases as you can see the texture popping up. There's also SVT in hdrp. This will although work with only asset bundles or assets built with project (excluding Resources)

#

in your case you should be able to load images without much stalling. Male sure you correctly manage the image loading and uploading part. don't try to load all textures at the same time. load them one by one using UWR

hollow wing
#

(solved)
hi having trouble with HashSet<..> with a custom MonoBehaviour

#

it seems the Contains method does not work as expected

#

in my case when there are 2 components in the HashSet, and I call Contains with one it sometimes does not return true

#

I checked GetHashCode that the custom MonoBehaviour is definitely in there

#

Is there something I'm missing here with HashSets and Components/custom MonoBehaviours?

#

oh well I think I made a mistake thanks 😄

silent rivet
#

Does unity have a way to view logs sent to Console.Error?

merry robin
#

if you're trying to read Console.-anything you'll need to use the Console callback methods

proud iris
#

An external C# DLL library in my Unity project does not seem to be protected/exempted from the Low Managed Stripping Level from WebGL. It functions correctly when compiled for Windows (Mono) but not for when compiled for WebGL.

I get this error.

#

I have a link.xml file in the project root assets folder. Though, it doesn't seem to do much.

<linker>
    <assembly fullname="FridayNightFunkin">
        <type fullname="FridayNightFunkin.Json" preserve="all"/>
    </assembly>
</linker>
cosmic basalt
#

@proud iris are you using il2cpp rather than mono?

proud iris
cosmic basalt
#

try changing it to mono in player settings -> configuration -> scripting backend

#

it might be because of the aot compiler not playing nice with external libraries

cosmic basalt
#

oh huh i thought you could do either on it

thick thorn
#

Well.. now it seems to pack all the work into one frame… not sure what’s going on… but seems to be better most of the time at least lol.

tough tulip
wet sail
#

hello, setting AnimationClip.legacy does not work in Build (has no effect at all), this has been a problem (at least for me) since unity2020, Can someone check if it works for you? if not i'd file a bug ?

wet sail
sly grove
#

I haven't tried it.

wet sail
#

Can you do that?

sly grove
#

But if it's as clear-cut as you say, should be easy to make a simple repro project

#

I don't have time.

wet sail
#

alright

dapper girder
#

Hey, I'm trying to bake a navmesh from a custom mesh. That mesh does not belong on any game object, which means I manually have to create a NavMeshBuildSource at the very least. Does anyone have any idea of how to do that? The documentation isnt really helping me

dapper girder
dapper girder
# regal olive What’s the solution?

Working with the navmesh surface package on git; if the surface navmeshdata is null you generate it via NavMeshBuilder.BuildNavMeshData and set it; if you're updating an already existing data, you update it via NavMeshBuilder.UpdateNavMeshDataAsync set it

#

If anyone needs concrete details just ask here

regal olive
dapper girder
regal olive
lapis arch
#

Hey guys, I have a small "problem" with visual studio code

#

When I'm defining a field it suggests it to have pascal case naming

#

for example I type:

#
private Sprite
#

And it suggests this name:

private Sprite Sprite;
shadow seal
#

Does it think you're beginning to create a method

#

I only suggest that because the icon matches the one above Awake

lapis arch
#

Yes

#

I think it does... Can I change that somehow?

shadow seal
#

Why? Then whenever you try and make a method it won't suggest names either

#

Plus in this instance, PascalCase is correct, it's a public field

lapis arch
#

well for me pascal goes only to non-fields

#

doesn't matter the access modifier

#

I just want to delete name suggestion for methods only, as it doesn't make sense to propose method names anyway

#

The editor suggests names based on the return type which is useless for me

livid kraken
#

Just like write your code and ignore the suggestion then

#

You dont have to click it

shell grove
#

Question: An IEnumerator is resettable by calling IEnumerator().Reset().
I store the IEnumerator in a Coroutine variable by calling var Couroutine = StartCouroutine(IEnumerator());
Now, Couroutine.Reset() does not exist. Is there a reason for that?

fresh salmon
#

Because the coroutine (iterator method) with all the neat methods like MoveNext and Reset is wrapped into the Unity Coroutine type that handles all the logic

devout hare
#

StartCoroutine doesn't return an IEnumerator

fresh salmon
#

It returns that wrapper

shell grove
#

Interesting. How can I start the IEnumerators then so that I can later access them again? Since StartCoroutine doesn't work?

devout hare
#
IEnumerator coroutine = MyCoroutine();
StartCoroutine(coroutine);
coroutine.Reset();

Untested, may or may not work
Intuition says it won't

#

If you want to reset a coroutine properly then stop it and start it again

shell grove
#

A coroutine stops at it's next yield instruction correct?

#

What I mean is that when I call StopCoroutine("Coroutine") it continues it's execution until it reaches the next yield. Atleast if I remember correctly.

devout hare
#

Functions always run to completion, which is either when the function ends or when there's a return statement. When you stop a coroutine, it stops immediately. But it may have done something before you stop it.

tough tulip
# devout hare ```cs IEnumerator coroutine = MyCoroutine(); StartCoroutine(coroutine); coroutin...

this will not work. last i remember this method was not implemented in unity.
the only way to restart a coroutine is to

private Coroutine coroutine;

void Restart()
{
  if(coroutine != null) StopCoroutine(coroutine);
  coroutine = StartCoroutine();
}```

its more convenient to use a wrapper class for this logic with MonoBehaviour and IEnumerator reference if this logic is being used at too many places
flint wind
#

StartCoroutine(coroutine);
Otherwise, the above is what I do too.

shell grove
#

Thanks 👍

sly grove
shell grove
#

true

normal cedar
#

A simple bool in while loop should also suffice

wicked bear
# shell grove Interesting. How can I start the IEnumerators then so that I can later access th...

If I could weigh in on the coroutine situation, IEnumerators can be manually progressed by using .MoveNext() on an IEnumerator, allowing you to progress them via your own triggers rather than a coroutine. So you call your IEnumerator method once to create an instance* of it, then call .MoveNext() on that instance at your own whim.

*instance is a simplification for education purposes only

#

An old screenshot from how I'm using it, where TeleOrb() essentially acts as a logical wrapper for the TriangleDash IEnumerator.

sly grove
#

It's not anything to do with coroutines (which are a Unity concept)

#

it's due to the fact that C# iterators are not resettable

shell grove
#

huh, that baffles me a bit

#

so IEnumerators cannot be Reset by calling Reset()?

sly grove
#

Depends on the particular IEnumerator you are talking about

#

an IEnumerator produced by an iterator method I.e. one that returns IEnumerator and using yield statements, cannot be Reset

shell grove
#
private IEnumerator ColorFade(int btn)
{
    release = true;
    RoundButtons[btn].GetComponent<MeshRenderer>().material.color = colors[btn];
    RoundButtons[btn].GetComponent<Light>().color = colors[btn];
    RoundButtons[btn].GetComponent<Light>().enabled = true;
    var duration = 1f;
    var elapsed = 0f;
    while (duration > elapsed)
    {
   yield return null;
   elapsed += Time.deltaTime;
   RoundButtons[btn].GetComponent<MeshRenderer>().material.color = Color32.Lerp(colors[btn], new Color32(255, 255, 255, 150), elapsed / duration);
   RoundButtons[btn].GetComponent<Light>().intensity = Mathf.Lerp(20f, 0f, elapsed / duration);
    }
    RoundButtons[btn].GetComponent<Light>().enabled = false;
    RoundButtons[btn].GetComponent<Light>().intensity = 20f;
    release = false;
    colorFade = null;
}
#

for example

sly grove
#

Can you maybe explain what your end goal here is? Resetting a coroutine is not possible.

shell grove
#

This one here

sly grove
#

Is there a reason you can't just call StartCoroutine(ColorFade(n)) again?

shell grove
#
    private IEnumerator FadeOut(int btn, AudioSource master)
    {
        var duration = 1f;
        var elapsed = 0f;
        var btnColor = colors[waveforms.IndexOf((i) => i == currentWaveform)];
        var wfv = wFV[waveforms.IndexOf((i) => i == currentWaveform)];

        if (currentMode == "Sustain")
            while (!release && !btnRelease[btn])
                yield return null;
        if (btnRelease[btn])
            btnRelease[btn] = false;
        while (duration > elapsed)
        {
            yield return null;
            elapsed += Time.deltaTime;
            master.volume = Mathf.Lerp(wfv, 0f, elapsed / duration);
            SquareButtons[btn].GetComponent<MeshRenderer>().material.color = Color32.Lerp(btnColor, new Color32(255, 255, 255, 150), elapsed / duration);
            SquareButtons[btn].GetComponent<Light>().intensity = Mathf.Lerp(20f, 0f, elapsed / duration);
            if (masterReset[btn])
            {
                elapsed = 0f;
                master.volume = Mathf.Lerp(wfv, 0f, elapsed / duration);
                SquareButtons[btn].GetComponent<MeshRenderer>().material.color = Color32.Lerp(btnColor, new Color32(255, 255, 255, 150), elapsed / duration);
                SquareButtons[btn].GetComponent<Light>().intensity = Mathf.Lerp(20f, 0f, elapsed / duration);
                yield return new WaitUntil(() => !masterReset[btn]);
            }
        }
        master.Stop();
        SquareButtons[btn].GetComponent<Light>().enabled = false;
        SquareButtons[btn].GetComponent<Light>().intensity = 20f;
        Destroy(masters[btn]);
        masters[btn] = null;
        fadeOuts[btn] = null;
    }
#

Currently I'm resetting the internal values back to 0 and halting the progress of the IEnumerator when masterReset[btn] is true

sly grove
#

You can stop a coroutine

#
Coroutine inProgress;
...
inProgress = StartCoroutine(FadeOut(n, a));
// then later:
StopCoroutine(inProgress);
// And start it again:
inProgress = StartCoroutine(FadeOut(n, a));```
tender quarry
#

When I try to extract textures from a .fbx file from blender, I get the error ```
EndLayoutGroup: BeginLayoutGroup must be called first.
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

Anywone knows what I can d about it?
I'm using Unity version 2020.3.25f1
regal olive
modest lintel
wicked bear
tender quarry
regal olive
wicked bear
flint wind
#

I've got events in my Character class for things like onNameChanged and onCharacterKilled and so on. They work just fine when another class has a 1-to-1 relationship with a specific character, like a UI Gauge that's just tracking a specific character's health stat.

The problem I'm running into is that I now have a class that needs to track the onCharacterKilled for multiple characters in combat, so that it can remove them from the turn order if they die. Problem is that onCharacterKilled doesn't send any parameters, so there's no way for the listener to know which character died.
I could update all my events to include this information, but it would be overkill for the listeners that only deal with one instance and already know which one it is.

Should I add the parameter of who is invoking the event to all my events, across the board, to resolve this? Or is there another way?
This will probably affect all the other classes I have events in, not just Character, eventually

modest lintel
#

This is a pretty bad example

#

But should get the point across

flint wind
#

I was struggling a bit on the implementation of that. But that {} notation is probably what I need.

#

I really should look into that notation more.
Thank you!

#

Oh, is there a way to then reference that delegate later and unsubscribe when the character dies?

modest lintel
#

Err, you have to store a reference to that delegate, and then use that to sub and desub

#

Not the cleanest way really

#

But, personally I'd just put the character info in the event itself if you are managing multiple characters

#

or have two sets of events

flint wind
#

I might have to in the end.
Also for things like onStatIncreased, I'd need to send back the Stat itself, and the Character that owns that stat, along with the amount

#

Since Stat doesn't have a reference to its owner, in order to avoid a lot of back and forth linking

#

But if I did do it this way, would you recommend:

public delegate void CharacterDelegate(Character character);
private Dictionary<Character, CharacterDelegate> characterKilledDelegateDictionary = new Dictionary<Character, CharacterDelegate>();

And later on...

for (int index = 0; index < activeActors.Count; index++)
        {
            CharacterDelegate characterDelegate = (Character character) =>
            {
                CharacterKilled(character);
            };
            characterKilledDelegateDictionary.Add(activeActors[index].character, characterDelegate);
        }
#

And then I'd just += and -= off the specified dictionary entry?

#

Actually, it's running into issues on -=
character.onCharacterKilled -= characterKilledDelegateDictionary[character];
Since CharacterDelegate has a parameter, on onCharacterKilled doesn't.

#

And +=, actually. I think I'm setting up the delegate wrong

#

So even though my delegate had the same signature in both classes, it still said it couldn't convert them. So I manually referenced the delegate in Character, and that seems to have got it to work

regal olive
#

A dictionary for the delegate registration/deregistration? What’s going on?

#

Sorry, slightly distracted. I think I may have just typed out my inner head thoughts out loud. I’m not saying anything is wrong but I did not expect to see a dictionary involved in a delegate assignment

#

…interesting code now that I’m reading it. Haha okay I’ll keep my thoughts to myself

modest lintel
#

They want to sub/desub anonymous functions. They need said anonymous functions because the parameters in their events don't have enough information

regal olive
#

@flint wind and/or @modest lintel what do you think about inverting the relationship between the two scripts? What if the character game object tell this character, erm, container(?) that it spawned and then when it dies?

I haven’t read enough for heaps of context, but I subscribe to the concept of code “telling other code what it wants to happen.” I’m still reading, so if this suggestion doesn’t make sense that’s cool. I figured I would surface the idea of flipping the relationship as it looks right now (on brief read).

modest lintel
regal olive
#

But that interaction is happening based on delegates. It seems like the ‘container’ shouldn’t really care about that?

flint wind
#

Some of my code will happily use the event on a specific item, like a Stat, and work just fine, because it's a 1-to-1 relationship. Like a UI health gauge tied to a health stat. It doesn't need to know what stat is firing the event, since that's implied.

But when I scale up to a larger scale and have multiple items to track, a single listener can't make heads or tails of which item is firing the event. Like in the case of my combat class needing to track dead characters, so they get removed from the turn order sequence. Also if a Character needs to track which of its many stats got modified.

I haven't made a call yet on which of the two methods to do:

  1. Have the delegates for all the events return the class that is firing it. So an event on a Stat for handling a onStatAmountChanged event would return the Stat and an int.
  2. Keep the events as they are, but any class that needs to track multiple instances will have a dictionary of delegates that it subs/unsubs and uses
  3. Something else that hasn't been mentioned yet?
sly grove
#

The official Microsoft way is something like:

public delegate void OnHealthChanged(object sender, System.EventArgs args);``` But I don't see it as appropriate for games due to extra GC overhead on the EventArgs instances
#

And some people of course swear by using Action<X, Y, Z> instead of custom delegate types but that's neither here nor there

flint wind
#

I was wondering about that too. My gut was telling me that an EventArgs class being made for every event call was going to generate a ton of garbage. Though i'm no expert on delegates... I was only guessing they don't generate garbage on calls?

sly grove
#

I don't think they generate garbage on calls, but I think the delegates themselves do live on the heap and will be GCed when discarded

flint wind
#

Action<> didn't seem very nice to use. At least with a delegate you can see the parameter names. With Action<> it's just arg arg arg arg arg...

sly grove
#

I agree but it's also not super relevant to the real question here

flint wind
#

True

sly grove
#

e.g. Action<Character, int, int> would be equivalent to my suggestion

flint wind
#

Yeah, I've also read that the compiler treats both Action and Delegate as the same for something like this

sly grove
#

I believe so, yes

#

it's purely a matter of readability/convenience tradeoffs

flint wind
#

In the case of Stat, it would need a reference to its owner Character, creating a circular reference structure. Just returning Stat in the event would not be informative enough to determine who owns it.

#

Alternatively I could have the container class for all of the stats on a character handle any outside event requests.
So a Stat returns a reference to itself and the amount with its events, and if something outside of the container class needs to know if a certain stat was changed, it subscribes to events on the container class, not the stat itself.

#

So event -> intermediate listener -> event -> final listener

regal olive
#

Using project specific language

#

Er, context aware language?

flint wind
#

I mostly don't want to pick up this project after a hiatus and have to decipher what past me was thinking when I wrote an Action signature 😄

regal olive
#

Ha, true! I use automated testing as my way of offloading human readable context off into the code. Revisiting a 6 month old project and reading what tests I wrote offsets the context degradation a bit.

flint wind
#

I think the best approach in this case is to have the event return the originator. Adding it saves me the hassle of managing a dictionary of runtime-created delegates, and the only price is extra parameters in the delegates involved.

regal olive
#

Okay here’s the message I was missing. Good intuition on pushing back a bit — making a dictionary that keeps track of delegates feels off. Great job on using events!! Yess!

Adding details about what character died into the payload of the event is definitely what I would expect. Even if most listeners don’t care who died, having that sort of information is a good idea. An event should provide a minimal yet enough contextual information to be a story. YMMV

regal olive
#

Also events are real hecking cool for tests

lofty inlet
#

So Application.persistentDataPath can vary based on the OS right? Is there any way to instead save files directly to the _Data folder of the build folder or create a folder inside the build folder and save to there?