#archived-code-advanced

1 messages ยท Page 143 of 1

carmine ermine
#

you can technically make two collections, one for flowers you can pick atm and another one for all flowers
and then whenevr u pick a flower, remove it and if it regrows, add it back from the all flowers list

probably not that smart but you dont need shuffling

compact ingot
misty glade
#

Whoa blast from the past

carmine ermine
compact ingot
misty glade
#

(btw Anikki, I finished that refactor shortly after that conversation and .. man what a thrilling feeling)

carmine ermine
#

anikki is the goat

misty glade
#

The best part is that the refactor was good in the sense that... it made everything so much simpler, so the functionality was there almost 100% out of the gate

#

Let's put @compact ingot to the test then.. I posted a problem and someone came up with a really nice solution, let's see if he beats it. You up for a challenge anikki? ๐Ÿ™‚

urban warren
misty glade
#

(or if anyone else wants a crack at it, be my guest):

#

I need an algorithm.

I have a game where each player has a grid, sparsely populated with griditems with a given level (1, 2, 3..). If 3 or more griditems are placed adjacently, they merge up into the next level griditem.

Players can move items around from turn to turn, and normal gameplay has all kinds of effects on the items on the grid.

I need an algorithm to populate N items on the grid without any chains (a "chain" is my name for a set of grid items that will merge up into the next level). I'm struggling to think of one. My requirements are:

A) easy to debug (no flexxing hard-to-understand or obscure algorithms, please - if they don't work, I need to fix them and I'm smoothbrained)
B) 100% success unless it can't be done (no "try a random configuration N times then give up" style algorithms)
C) relatively efficient (situations where I'm populating 99 items on a 100 square grid shouldn't break the CPU)

Any thoughts/ideas?

compact ingot
#

how much do you want to control the initial state... are one move to victory situations allowed?

misty glade
#

Yup - the only constraint is that there can't be any chains in the initial state

#

FWIW there's no "victory" per se, here's a quick clip of gameplay

compact ingot
#

i'm sure there is a property of prime numbers and division that would guarantee such a pattern... but i'd just do a spawn, forbid all adjacent cells and continue with checks against the forbidden cells

#

that is extremely straight forward and can be extended in behaviour to have more constraints

misty glade
#

that's pretty close to what I'm doing, but not forbidding all cells, only forbidding cells that create chains

#

but I don't think that it's 100% comprehensive

compact ingot
#

if you aim to do it non-sparsely, maybe you need something more deterministic... a space filling curve maybe, or good old LCG with additional checks

misty glade
#

I worry that fail cases will be high

#

it'll be sparse, since there's no "swap tiles" functionality, only move to an empty tile

#

LCG..?

compact ingot
misty glade
#

oh, right

compact ingot
#

the general idea of space-filling curves (or LCG like things) is interesting for generators that can fill a thing without the "rng + check" approach that fails on non-sparse spaces

#

also nice would be a wave function collapse approach, but that is slow and does a "1000" check but is more (art)directable

long ivy
misty glade
#

i worry the fail case % will be high

#

hard to quantify

compact ingot
#

you could also just incrementally check if the candidate would produce a chain, instead of checking the whole board each step... then you just need to iterate all cells once and done... even if the board is almost full

misty glade
#

oh, yeah, that's a nice optimization

long ivy
misty glade
#

like instead of making the X's on each succesful deploy, try a deploy and if it fails, THEN take that out of the pool of available spots

#

Right, I mean, that's what I'm doing

#

I have N lists of grids where N is the number of levels an item can be. I initialize these grids with all the spots on the grid. Each time I succesfully deploy, I remove that spot from all the grids.

#

Then I check Grids[N] for spaces that will create a chain and remove those from Grids[N]

#

(but i don't need the above step - i can just check if the try-placement failed and remove it from Grids[N])

long ivy
#

well if efficiency is your goal, phrases like "try-placement" and "skip that efficiency step" sound odd to me

misty glade
#

like this is a "fail" case but clearly we can do more than 10 "ones" on a grid

#

I mean, I don't really care too much about efficiency, but if I want to populate 90 items on a 10x10 grid it shouldn't break the bank, so to speak

long ivy
#

it sounds like you need a backtracking algorithm to me now, if N is large enough that there are arrangements where you can't fit N items on the board due to your rules

misty glade
#

Here's my current thought-algorithm, and for simplicity I'll use actual numbers - grid size = 25 (5x5) and initial elements = 10:

A) Create a bunch of List<GridPoint> named OpenSquares with 25 items. These are valid placements for an item of a certain level.
B) Create a new GridItem. Grab a random GridPoint from the OpenSquares list for that level. Remove it from that list.
C) Remove all GridPoints from that OpenSquares list that would create a chain if an item were deployed there.

Repeat 10 times.

long ivy
#

so by fail case do you mean that you run out of open squares before you run out of items to place?

gray pulsar
#

if your newest placement creates a situation where the available spaces left are fewer than the number of items left to place, you know you have an invalid configuration. Instead of throwing the whole thing out, undo the last placement and try it somewhere else. ??

misty glade
#

infinite number of times? some fixed number of "strikes"?

#

My early thought is to .. not sweat it, and just try to place an item until there's nowhere valid to place it, and then stop adding

#

(and just make that a part of the game)

#

I mean, really, if that's the case, the board is going to be "pretty loaded" as it is, and any move should grant a merge

compact ingot
misty glade
#

Yeah, true

compact ingot
#

not sure but you would probably have to pin the rng sequence to be replayable

misty glade
#

I just tried out my "simple" solution (ie, if there's no open spots, just "fail to create" and continue) and ran a test

#

20,000 battles with 10 items per player, 0 failures

#

i'm going to bump up x items per player and see where it starts failing

compact ingot
#

Good enough Iโ€™d say

#

can fail at 13+ (guesswork)

misty glade
#
[verbose][12:28:16.27] Grid items:10 Failures over 10,000 boards:0
[verbose][12:28:17.22] Grid items:11 Failures over 10,000 boards:0
[verbose][12:28:18.26] Grid items:12 Failures over 10,000 boards:0
[verbose][12:28:19.38] Grid items:13 Failures over 10,000 boards:0
[verbose][12:28:20.59] Grid items:14 Failures over 10,000 boards:0
[verbose][12:28:21.89] Grid items:15 Failures over 10,000 boards:4
[verbose][12:28:23.27] Grid items:16 Failures over 10,000 boards:24
[verbose][12:28:24.73] Grid items:17 Failures over 10,000 boards:68
[verbose][12:28:26.28] Grid items:18 Failures over 10,000 boards:226
[verbose][12:28:27.90] Grid items:19 Failures over 10,000 boards:530
#

reasonable performance, too imho

#

putting 19 grid items on a board of 25 squares seems like it should fail a lot more than 5% of the time

#

Good enough for government work, and I'm on to the next task. Thanks y'all ๐Ÿ™‚

#

there's probably some small optimizations in here but .. it's fine enough for now

lone elk
misty glade
#

particle effects trigger automatically when instantiated i believe?

lone elk
misty glade
#

i'm not an expert on them but when I was dabbling I vaguely remember having to set some property to auto play, off

lone elk
#

Yeah, it's turned off, and what's even more weird is that it gets triggered by script that handles shooting, which has no references to particle systems

#

And it somehow triggers multiple particle systems, but that's not showed on gif above

misty glade
#

that is odd.. and the prefab itself has play on awake = false?

#

i mean, i suppose it should

#

Not sure, sorry!

lone elk
lone elk
stable spear
#

there's no repeatable event that triggers it?

lone elk
#

Code for shooting

void Shoot()
    {
        _isShooting = true;
        if (canShoot)
        {
            if (Time.time > _nextFire)
            {
                _nextFire = Time.time + fireRate;
                GetComponent<TraumaInducer>().Shake();
                GameObject clone = Instantiate(_currentProjectile, transform.position, transform.rotation);
            }
        }
    }

And... nothing here references particles

stable spear
#

well there's two things going on that could be relevant. The Shake() and the Instantiate

#

is the particle system attached to the projectile?

lone elk
#

Script which controlled emissions is turned off

public class EmitterTestScript : MonoBehaviour
{
    private ParticleSystem _particleSystem;


    void Start()
    {
        _particleSystem = GetComponent<ParticleSystem>();
        if (_particleSystem == null)
            _particleSystem = Utility.FirstChild(gameObject).GetComponent<ParticleSystem>();
    }

    //public void Emit() => _particleSystem.Play();
    public void Emit()
    {
        _particleSystem.Play(false);
    }

    public void StopEmitting() => _particleSystem.Stop();
lone elk
#

transform.position, transform.rotation from above code snippet is position of Pod 1 -- it spawns projectiles
And it has child Particle System, which for some reason triggers with shooting

#

Goddamn.

#

I didnt write the Shake script, it's an asset
I do not know why does it do this

#

My bad. Thanks a lot

lone elk
long ivy
#

drops and inventory are reference types. You'd need to change them to NativeArrays and fix your allocation in ProgressFurther

#

I think putting this in a job is suspicious as well. Are you running this hundreds of times per frame?

misty glade
#

value types can still hold references to reference types

#

if you come from a C/C++ background, just think of reference types as pointers to objects .. copying the struct with a reference type makes a new pointer to the existing object (if it isn't null). If you set the pointer to a new()'d up object, the old object won't be GC'd if there's some other struct with a pointer to it

#

although I suppose that's true of reference types that have a reference type member

long ivy
#

structs are, but arrays aren't. It's not complaining about the contents of the array, it's the array itself

timber saddle
#

In the Editor, how can I get the position and size of the game area relative to the screen?

#

I'm making a native editor plugin that opens a window on top of Unity, and I'd like to place this window somewhere based on that area, but I can't figure out if that's possible to get.

urban warren
# compact ingot https://discord.com/channels/489222168727519232/885300730104250418/8997648454764...

Hey, I know it is a lot later, but I have been messing with and the LCG, I understand how it works now that I have written it out my self and played with it. (Much simpler than I originally thought, feel a bit silly for thinking it was complex at first)
The only thing I am unsure of is the increment, I feel like it needs to be a 'magic' number otherwise it will not work properly? But I'm not sure what. The comment leads me to think it needs to be a co-prime to the sample size? Is this correct?

#

I read (parts) of the wiki, but admittedly a good portion of the more technical parts go over my head.

urban warren
#

You can use Display to get the width and height of the screen iirc.

#

You should be able to use GUIUtility.GUIToScreenPoint(...) to get the main window position in screen space if it isn't already.

long ivy
timber saddle
timber saddle
timber saddle
#

Thank you both @urban warren @long ivy ๐Ÿ˜

ember geyser
# lone elk Greetings gentlemen. Anyone encountered problem when particle system just trigge...

Yes, I know this "feature". It's something to do with the parent particle systems of a child particle system, and when you select it in the Editor. It doesn't happen in builds because you can't select the objects that cause this to happen in the hierarchy in a build, but can happen in Edit or Play mode in the Editor. Pushing the Stop Button particle system popover controller (with the speed and pause buttons) with the highest object with a particle system selected turns this off.

#

BUT... only until the next time you select an object in this section of your hierarchy.

rough copper
#

I customized the lego microgame, But how can i make it for mobile
I want to move jump in mobile but how?

grand falcon
#

How can I change sprite of each frame in a predefined animation at runtime with code?

olive totem
#

Is there a reason you need native arrays?

#

And like the error says, it only works for unmanaged types

#

Yeah pretty much anything in C# is managed unless you interact with a native plugin

compact ingot
minor girder
#

Chess person again ๐Ÿ˜…
So I've looked into the Command Pattern and Undo/Redo functionality and that seems perfect for what I need. I'm just having some difficult time to warp my head around it and how to manage it. I have .json files that have games stored (list of moves done in the previous games). I have a menu which shows all of those stored games. On the press of the game button, .json file should load, a board should show up and, by clicking the arrows on the screen, moves should play out.

compact ingot
minor girder
#

figured that is a step one in that process. I should do it on the button click right? Not sure where should I do the parsing, in which script

compact ingot
runic tendon
#

Is it possible to have generic classes and a non generic one without repeating code? like, how c# has both an Action<T> and plain Action though I don't know how those are implemented.

compact ingot
minor girder
compact ingot
urban warren
minor girder
# compact ingot Check current discussion in <#763495187787677697> on composition

ah, i know what composition is ๐Ÿ™‚ am lost in figuring out how to piece everything together.
to be a little bit more clear - I click a button that has a name of the file in the text component. Click should load a filename.json file and parse it into commands. i understand the pieces, but i don't know how to put it together

compact ingot
urban warren
compact ingot
#

btw. there is no algorithm to find the "nearest" prime number that is any different from finding prime numbers in the first place...

urban warren
compact ingot
#

but there is a very neat wikipedia page with all kinds of subsets https://en.wikipedia.org/wiki/List_of_prime_numbers

A prime number (or prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself. By Euclid's theorem, there are an infinite number of prime numbers. Subsets of the prime numbers may be generated with various formulas for primes. The first 1000 primes are listed below, followed by lists of notable types of prime...

compact ingot
urban warren
compact ingot
hollow garden
urban warren
hollow garden
#

and it's also used a lot in art

#

you see it like everywhere

compact ingot
hollow garden
#

in nature, the fibonacci sequence,

compact ingot
#

the length of all your bones in your limbs, relative to each other, e.g. in your fingers is 1:1.618

urban warren
#

Fascinating.

compact ingot
hollow garden
#

yeah, the higher in the fibonacci sequence you go, the better of an approximation of the golden ratio you get

compact ingot
#
global  _fib
section .data
section .text
    _fib:
        mov     rcx, rdi    ; Add argument to rax
        mov     r10,  1     ; n
        mov     r11,  0     ; n-1
        mov     r12,  0     ; n-2
        _fibloop:
        dec     rcx
        mov     r12, r11    ; n-1 becomes n-2
        mov     r11, r10    ; n becomes n-1
        mov     r10, 0      ; n = 0
        add     r10, r11    ; add n-1 to n
        add     r10, r12    ; add n-2 to n
        cmp     rcx, 0      ; exit loop when counter == 0 reaches 0
        jg      _fibloop    ; if rcx > 0
        mov     rax, r11    ; copy n to return register
        ret                 ; return
``` i guess they make you do that so you can appreciate C and not hate it
hollow garden
drifting galleon
hollow garden
#

not everyone here can read asm

compact ingot
# hollow garden not everyone here can read asm

funnily enough, ASM is so simple that anyone can understand it in maybe an hour, kinda like lego... its just completely mindboggling to understand something you have written a week later.

hollow garden
#

i see

urban warren
compact ingot
urban warren
drifting galleon
compact ingot
#
IL_0085: ldarg.0      // this
IL_0086: ldfld        class [mscorlib]System.Collections.Concurrent.ConcurrentDictionary`2<string, class Juniper.ProxyStoreEntry> Juniper.ProxyStore::_store
IL_008b: ldarg.1      // key
IL_008c: ldloc.0      // 'CS$<>8__locals0'
IL_008d: ldfld        class Juniper.ProxyStoreEntry Juniper.ProxyStore/'<>c__DisplayClass13_0'::entry
IL_0092: ldloc.0      // 'CS$<>8__locals0'
IL_0093: ldftn        instance class Juniper.ProxyStoreEntry Juniper.ProxyStore/'<>c__DisplayClass13_0'::'<Set>b__0'(string, class Juniper.ProxyStoreEntry)
IL_0099: newobj       instance void class [mscorlib]System.Func`3<string, class Juniper.ProxyStoreEntry, class Juniper.ProxyStoreEntry>::.ctor(object, native int)
IL_009e: callvirt     instance !1/*class Juniper.ProxyStoreEntry*/ class [mscorlib]System.Collections.Concurrent.ConcurrentDictionary`2<string, class Juniper.ProxyStoreEntry>::AddOrUpdate(!0/*string*/, !1/*class Juniper.ProxyStoreEntry*/, class [mscorlib]System.Func`3<!0/*string*/, !1/*class Juniper.ProxyStoreEntry*/, !1/*class Juniper.ProxyStoreEntry*/>)
IL_00a3: stloc.1      // newProxyStoreEntry
``` LOOKs cursed IMO
hollow garden
#

even for a simple hello world program in rust it's like 200 lines

olive totem
#

The assembly instructions are simple but still there's quite a lot about them to understand

hollow garden
#

i lied it's 614 lines

#

but most of it is not related to the code

#

or, it is in some obscure way

compact ingot
#

IL is not so bad for straight up calculations (that IL is just part of it... but its like that throughout)

#

but when doing any method calls... it gets out of hand... visually... but really any assembly language would

olive totem
#

Lucky for us unity devs there's no need to write this

hollow garden
olive totem
#

Rust is ugly enough by itself

hollow garden
#

damn

#

i think this looks rather good myself

#

apart from the whole <const N: usize> thing of course

olive totem
#

No idea why they couldn't do a more C/C++ look with the addition of traits

hollow garden
#

well they at least did it good with generics

#

nobody who's seen templates is gonna say they look better

olive totem
#

Well yeah that's kind of messy and gets wild real quick

compact ingot
#

i think rust somewhere got lost when they tried to make it actually real... they had to go hard in one direction and that direction ended up different from the original intent to make a "nice" language

hollow garden
#

how is it not a nice language

compact ingot
#

well, its hard to get it to compile ๐Ÿ˜‰

hollow garden
#

ok fair

#

but that's one negative that adds a whole lot of benefits

#

for one you will never get data races

compact ingot
#

and the compiler is slow AF

olive totem
#

I can't comment on that but C++ as well so you end up using cmake

compact ingot
#

"not nice" only really refers to the absence of convenience... not the language itself... its pretty neat

hollow garden
olive totem
#

So I've been told that it's neat but just looking at it makes me feel awkward

hollow garden
#

that's how i felt like at the beginning as well

compact ingot
compact ingot
hollow garden
#

personally i don't know what people are talking about when they look at not so complicated rust code and are like ew

hollow garden
#

i guess but most of it is pretty similar apart from like... everything

olive totem
#

Yeah sounds like solid reasoning to me, Rust users keep telling me that C++ is dangerous but I just find it nice to use when appropriate for the task at hand

hollow garden
#

they only tell you that C++ is dangerous because unsafe stuff

#

any rust programmer will recoil in horror at the mention of that word

compact ingot
olive totem
#

I like that unsafe space

hollow garden
compact ingot
#

also... safety and performance are kinda mutually exclusive

olive totem
#

One of the advantages of C++ is that it won't tell you 'hey this is stupid'

#

It just lets you, assuming you know what you're doing

hollow garden
compact ingot
hollow garden
#

yeah i guess

#

rust forces you to jump through those hoops

#

which can be a bit uncomfortable at times

#

but once you can figure out how to avoid being forced it's pretty nice

compact ingot
#

maybe also forces you to change your way of thinking.... cant imagine a JS programmer adopting rust anytime soon

hollow garden
#

oh yeah

olive totem
#

One thing I dislike about C# is the effort you have to do to keep memory use stable

olive totem
#

You get so used to sprinkle the new keyword everywhere

#

And relying on the garbage collector to help you

compact ingot
#

i find memory management (when you want to manage it yourself) in C# is WAY more complicated than in C++

olive totem
#

It is

#

There are some gotchas though but they come with time

#

Still feels a bit iffy

compact ingot
#

i mean in c++ you just do it... allocate whatever you want, as simple as you want... and in C# you need 1000 APIs for every degree of safety you might still want

#

and none ever feels explicit...

#

but at least its possible i guess

olive totem
#

Yeah it is, if you care enough to write some utilities yourself ๐Ÿ˜›

alpine herald
#

Do you know how to save a GameObject with the components on runtime? and load it when need it (for rollbacks)

compact ingot
olive totem
#

There's no out of the box solution that I know about

alpine herald
compact ingot
olive totem
#

Your best bet is to look in the asset store

compact ingot
#

what would you consider default components?

olive totem
#

Or if you're going to make something yourself, keep it simple so you only store whatever is needed to restore state

#

Still it's probably not going to be very pretty if you want to make a generalized thing for it

compact ingot
#

i'd expect a generic solution to have the performance of C# implemented in python

olive totem
#

It might be possible to take the entire game object and somehow dump the entire binary blob somewhere into memory

#

But no idea how to exactly go about that

compact ingot
olive totem
#

Yeah good point, won't work with reference types

compact ingot
#

ideally game state should not require references... its probably a good idea to code all game-state relevant stuff with serialization/restore-from-data in mind... then its no big deal...

misty glade
#

You don't want to save gameObjects, you want to save POCOs and have good functionality to create/save the GOs from the POCOs

rain cipher
#

References are fine your serialization system just needs to handle it, ie serialize a ref to an ID then reverse on deserialize

misty glade
#

if you just try to natively serialize POCOs game objects (oops, edited) you'll have quite a bit of bloat in your serialized data (JSON, byte[], whatever), whereas if you do it yourself you can save it to a human readable format

urban warren
#

Something to keep in mind when saving/loading GameObjects or Components, you will most likely need to assign a id to each so that you can restore references when loading. I looked in to this a bit ago and the best I could come up with is to keep a dictionary of all GameObjects and Components in the scene and have a id as the key.

compact ingot
minor girder
compact ingot
# minor girder Yeah, basically the architecture if I can call it like that? Like, where to put ...

basically every -thing- that you can readily give a name, or that appears to be a discrete feature can (and maybe should) be a separate class... so dont worry too much about that... for example the parser would be a some regular C# class (no monobehaviour/SO), that you instantiate with some configuration on how to parse (if you need configuration)... and a method .Parse(inputText)... the return type is whatever you decide is convenient to you. Somewhere else... maybe in an instance of a ManagerClass, you keep track of all the parsed things... and on a instance of a PresenterClass (this is a Monobehaviour) you make the parsed stuff show up in the game

misty glade
#

Also as your codebase grows, take time every few weeks to decide if things are in the right place and ... clean house before it's overwhelming to do so. Having logic in non-intuitive places is a real bummer when you're trying to find something weeks/months later.

#

I'm also a fan (lately) of placing things in nested namespaces that match the directory structure so you don't have to remember two separate "things" to find something (a namespace and a directory)

#

How much I'm actually sticking to that is ... a separate topic.. ๐Ÿ˜›

compact ingot
misty glade
#

heh

#

i've actually considered moving pretty strongly to TWAE, stylecop analyzers, etc

compact ingot
#

i think squggly lines do more for code cleanness than any book by uncle Bob

misty glade
#

(ready to holy-war?) sometimes I like to break my own rules though because I feel like something like the following is better than lots of braces or one line if-clauses with indents

#

(sec trying to find the snippet)

#

it's likely to induce some ๐Ÿคฎ .. hopefully my feelings aren't hurt after though ๐Ÿ˜›

compact ingot
misty glade
#
        private static void PaintDestroyChain(GridItemDictionary gridItems, GridItem currentGridItem, int chainId, int destroyIntoId, int destroyIntoX, int destroyIntoY)
        {
            currentGridItem.ChainId = chainId;
            currentGridItem.DestroyIntoId = destroyIntoId;
            currentGridItem.DestroyIntoX = destroyIntoX;
            currentGridItem.DestroyIntoY = destroyIntoY;

            GridItem N = gridItems.UnsafeFastGet(currentGridItem.X, currentGridItem.Y + 1);
            GridItem E = gridItems.UnsafeFastGet(currentGridItem.X + 1, currentGridItem.Y);
            GridItem S = gridItems.UnsafeFastGet(currentGridItem.X, currentGridItem.Y - 1);
            GridItem W = gridItems.UnsafeFastGet(currentGridItem.X - 1, currentGridItem.Y);

            if (N != null && N.Contents == currentGridItem.Contents && N.ChainId == 0)  PaintDestroyChain(gridItems, N, chainId, destroyIntoId, destroyIntoX, destroyIntoY);
            if (E != null && E.Contents == currentGridItem.Contents && E.ChainId == 0)  PaintDestroyChain(gridItems, E, chainId, destroyIntoId, destroyIntoX, destroyIntoY);
            if (S != null && S.Contents == currentGridItem.Contents && S.ChainId == 0)  PaintDestroyChain(gridItems, S, chainId, destroyIntoId, destroyIntoX, destroyIntoY);
            if (W != null && W.Contents == currentGridItem.Contents && W.ChainId == 0)  PaintDestroyChain(gridItems, W, chainId, destroyIntoId, destroyIntoX, destroyIntoY);
        }
#

i break all kinds of rules here

#

wide lines

#

if statements on the same line as the clauses

#

one letter variable names

#

etc

#

but......... it seems easier to visually parse what this method does to me

compact ingot
#

i dont think these are violations, they have a pattern, make errors easier to spot

#

its also perfectly readable

misty glade
#

the above method is probably my most "difficult" method in my 22k line codebase.. in the sense that it's not boring/straightforward code

#

and if I tell you one sentence - "it's a recursive method that traverses each square in a grid and paints touching grid items with a ChainId" you can mostly grok that pretty quickly

#

(which hopefully means I can grok it 6 months from now when i find it has a bug of some sort) ๐Ÿ™‚

compact ingot
misty glade
#

so, impromptu code/architecture review Q for you.. i have a server that listens for incoming messages, and then routes them to a dispatch (AND processing) method.. but as the number of different types of actions a player can take increases, this method is .. quite huge.. would you consider that to be a problem? I'll paste in a sec

compact ingot
misty glade
#

I recently .. refactored that from something where I did the one or two lines of "processing" inline, in the dispatch method

#

eg:

compact ingot
#

anything with a pattern collapses to one line of code in my mind

#

so i dont mind that at all

misty glade
#

so that, in a nutshell, is the "opposite" of this - it does the processing AND the dispatching inline

#

which... saves me from having to do little tiny methods that have one line of code?

#

but this method is basically untestable

compact ingot
# misty glade <https://pastebin.com/wXUnkkMh>

i'd intuitively extract those cases into methods. but i'd hate myself for it in two weeks, cause i dont trust that the method does what it says... and in your code i see what it does

misty glade
#

(I think I consider this method to be bad)

#

Maybe a more important question - would you extract functionality to a method if it "Does One Thing" (even if it's only ever going to be invoked from one place)?

compact ingot
misty glade
#

by... testing each cyclomatic complexity branch?

#

like, in the test case

compact ingot
compact ingot
# misty glade by... testing each cyclomatic complexity branch?

by only doing stuff that you know is correct... like using a FSM that you know is correct, and doing your transitions in a visually clean way so you can spot errors visually... then all errors must be outside the complex configuration code (the FSM definition or the switch)

misty glade
#

Hm.. OK. I think I have a gap between my current state and that state. I don't have a test framework where I can test individual units of code or FSM correctness (or equality between client/server). I'm thinking that the further I go without implementing it, the worse that task will be when I bite into it.

#

So far, I'm pleased with the nature of the bugs in this setup - ie, they're easy to spot, easy to fix, behaviour isn't a mystery (it's more like "oh yeah I forgot to add their hitpoints to the action"). But... I wish there were a bit more proactive bug identification, especially from existing working functionality, so I don't go down a path where I add some new game logic and break existing logic inadvertently (and miss it because I fail to test it)

compact ingot
# misty glade So far, I'm pleased with the nature of the bugs in this setup - ie, they're easy...

i try best i can to make my systems as independent from other stuff as possible such that they cannot break by way of outside changes,,, i do that mostly by convention not really by using interfaces and stuff like that. most important part of that is not making any assumptions about stuff that is out of control of the system itself... like... never assume there is only one camera, one network connectior, one database, one screen, one joystick, one player, ... or any other of the game elements

cursive horizon
#

if you split it out so that you resolved dependencies, then passed them into methods which defined them explicitly, it would make those methods more testable and make it easier to tell when this stuff breaks (because you'd have explicit contracts for each command)

misty glade
cursive horizon
#

i guess you are already kind of doing that, since this is resolving and creating the battle actions

compact ingot
#

ad-hoc dependency injection

cursive horizon
#
   case PlayerActionFieldMove paFieldMove:
                        GridItem playerMovedToFieldItem = b.Grids[actingPlayerGuid].Items.Get(paFieldMove.Id);```
#

that has an implicit dependency on that GridItem

#

and Demeter would be apalled at how it resolves it, but I don't think he's that important really

misty glade
#

Technically that "can't fail" since that is checked in the IsValid() method.. or is that not what you mean?

#
                case PlayerActionFieldMove pafm:
                    if (b.Grids[actingPlayerGuid].Items.Get(pafm.Id) == null) // Check to ensure the grid item exists
                    {
                        e($"Player {StringUtils.GetName(actingPlayerGuid)} tried to move an item to the field that doesn't exist ({pafm.Id}).");
                        return false;
                    }
                    break;
#

Or do you mean that there's a dependency on the GridItem class? (which is OK, I think? it's a POCO)

cursive horizon
#

i guess i mean that this 'endpoint' requires an instance of GridItem to do its job

#

but that information is internal to it, rather than defined by any sort of contract

#

it's like a function that reaches outside of its scope to get some information instead of that information being passed in

#

technically it is passed in, because you are passing the entire battle state around here

#

but if you consider this case, it doesn't actually need the entire battle state, it just needs that one grid item (or maybe it does, but it might not!)

misty glade
#

right, I think I see what you're getting at

compact ingot
#

basically, as a rule of thumb, use only one . when accessing referenced data

cursive horizon
#

this function needs a GridItem, but what it gets is an entire battle, and then it has to know how to get a griditem from a battle

misty glade
#

OK.. that's a good idea, actually, minimizes the chance of accidental NREs

cursive horizon
#

if you make the contract more specific, you can work within a more constrained scope (which is good here, i'd argue)

misty glade
#

I think that there might be a case for using that entire battle state for any of the processing functions because "who knows" what sort of crazy things those methods will do later, and if the designer changes his idea of what the player action should do, I can leave the method signature intact

cursive horizon
#

yeah, that's always the sticking point in games

misty glade
#

(just playing devil's advocate - not sure if I personally believe that)

cursive horizon
#

you do sort of want to pass the whole state around

#

but! i would argue that even with that being the case, you should have some phase where that state is narrowed down to the specifics you actaully need to do a given action

misty glade
#

Right.. my "processing" type functions can be static, and just take a reference to the root FSM (a "Battle") - although it makes the processing a little messy, they have to dig deep into that FSM heirarchy to get what they want

cursive horizon
#

i think the web world does this stuff pretty well

#

something like:
Request (player action) -> Router -> Endpoint -> Commands

#

the router is what you were asking about earlier (basically a big file that says what should go where)

#

that sends information to the endpoint, which would resolve entities, do any extra validation, etc

#

and then pass that data onto specific commands, which are what actually modify the state and only take in exactly the data they need for whatever it is that they do

#

that keeps your specific commands testable in isolation (and makes debugging easier because you can build and execute commands from any context as long as you can resolve their dependencies somehow)

misty glade
#

example: https://pastebin.com/JRjG2atq This is a special ability, it's a static method that takes a reference to the battle and "battle actions" (the ultimate output of the method) along with some things that it needs specifically (the "Person" using the ability, the attacker and defender and so on), but this method does the work of digging into the FSM and moving stuff around.. if the game designer says "Ok we don't want to move items from one grid to the other grid but instead from the grid to field (another location in the battle) we can do that without any signature changes

misty glade
cursive horizon
#

i actually think you are already doing most of that, but you could go further if you wanted

#

yep, keep narrowing it down

misty glade
#

(then the ultimate method that does the work just has the minimal set of what it needs, and is ultimately much easier to test as a positive consequence)

#

instead of trying to test the dispatch method for correctness

#

ie - the dispatch methods correctness is basically - ensure the incoming list of actions get dispatched to the proper place (easy to test) and not make sure the incoming list of actions is correct (impossible/difficult to test - many Fakes/Mocks needed, huge variety of inputs, etc)

#

awesome conversation guys, thanks @cursive horizon @compact ingot

cursive horizon
#

yeah, i think it can be helpful to have a validation layer between resolving the entities and dispatching the commands so that you can confirm stuff like that

#

and if you define your 'validators' consistently, you can test those in isolation, or whatever part of that stack you want to

misty glade
#

yeah I don't think I should also be doing IsValidAction(PlayerAction) but instead dispatching the validation to the narrowly defined validator, as well - so IsValidPlayerFieldMove(PlayerActionFieldMove) or whatever

#

that way I'm less likely to have failures in the server validators themselves - which is Really Bad (since it can crash the server)

#

then the validator dispatch has a narrow success criteria as well - does the action get properly dispatched for validation - versus the behemoth of validation it's becoming

cursive horizon
#

yeah, and validators are just a valiable concept

#

valiable? valuable

#

it's useful to be able to like...select some rules to apply to something in the inspector

misty glade
#

valuable validators are valiable

cursive horizon
#

so if you have, like, adjacency rules defined as stacks of validators, you an build an inspector ui to let you apply them to certain actions

#

and then you can add/remove them at runtime as players unlock new abilities or whatever

#

basically games are made up of rules so it's helpful to represent those consistently so you can do stuff with them

#

game logic as data

misty glade
#

right... and you've really nailed a core.. architecture challenge of this particular game. We intend to add lots of wacky abilities over time so .. it's really critical that we don't create an environment where adding a new ability is going to break other things

#

And we also are really going to require automated testing because the combinations of abilities is likely to be huge over time

#

it's actually an understated marvel how well companies that produce games like magic the gathering, hearthstone, or Ring of Pain (shoutout @austere jewel ) manage big complexity

cursive horizon
#

in my experience they do it with a lot of pain and suffering on the part of people working on it ๐Ÿ˜„

misty glade
#

haha

fallen halo
#

in state design pattern: if there is a transition from the superstate to another state
and in the substate of that superstate there is another transition to another state, i encounter problems. Is there any way to rectify this problem

queen plover
#

Are you trying to have state machines that contain state machines?

raw wind
#

I'm trying to implement a Serializable HashSet

#

but I'm having issues

#
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class SerializableHashSet<T> : HashSet<T>, ISerializationCallbackReceiver
{
    [SerializeField] 
    private List<T> values = new List<T>();

    public SerializableHashSet() : base() {}
    
    public SerializableHashSet(IEnumerable<T> collection) : base(collection) {}

    public void OnBeforeSerialize ()
    {
        var cur = new HashSet<T> (values);
        
        foreach (var val in this) {
            if (!cur.Contains (val)) {
                values.Add (val);
            }
        }
    }
    
    public void OnAfterDeserialize ()
    {
        Clear ();

        foreach (var val in values)
        {
            if (val != null)
            Add (val);
        }
    }
}```
#

I'm getting this error in the console repeatedly...

#
System.Collections.Generic.HashSet`1+Enumerator[T].MoveNext () (at <351e49e2a5bf4fd6beabb458ce2255f3>:0)
SerializableHashSet`1[T].OnBeforeSerialize () (at Assets/Scripts/Utilities/Collections/SerializableHashSet.cs:21)
UnityEditor.HostView:OnInspectorUpdate() (at /Users/bokken/buildslave/unity/build/Editor/Mono/HostView.cs:354)```
#

So that's from the line that says... foreach (var val in this) {

#

Can anyone help with this? It's had me stumped for hours?

gray pulsar
#

I swear I saw discussion about serializing hash sets here yesterday

#

I guess that's in the context of editor scripting, but maybe it'll get you on the right trakc?

gray pulsar
stable spear
# raw wind Can anyone help with this? It's had me stumped for hours?

This is complete conjecture, but it is possible that this == null in the call to OnBeforeSerialize. I see references to Unity not supporting null references to classes during serialization. It might assume all references are valid, and it could invoke OnBeforeSerialize in a low-level way, which does not do null checking.

hollow wing
#

Is it valid to use tasks in Unity?

stable spear
#

you're not getting something important

#

async/await/tasks are just state machines, like coroutines

#

To actually RUN a task, requires additional machinery

#

either a thread pool and a scheduler

#

or something else

#

if you schedule your tasks onto a thread pool in Unity, it's going to break

#

because Unity's objects are not thread-safe

#

if you schedule your tasks using a plugin, it will run them on the main thread like coroutines

hollow wing
#

you're still talking about the package you linked I assume, correct? (as the plugin)

#

that is helpful

stable spear
#

or any equivalent package, sure

hollow wing
#

and you answered my above question with "no" then? basically: "no - just using tasks will break unity"

#

I'm asking to reassure I understand you properly

long ivy
#

using tasks is fine. Using tasks that you're running on another thread, you must be careful with

stable spear
#

Again, its not just "no", because it is possible to use them, just not with a thread pool

#

Unless you are performing operations that are independent of Unity

#

(but in that case, I would recommend putting the code in a .dll)

hollow wing
#

isn't having a thread pool the default?

#

or let me ask differently

#

if I start 10000 tasks, isn't it likely that one of these is run on a different thread than the main thread?

#

thus would possibly break the engine with API calls

#

my understanding is I have little control on which thread a task is run (except I use that plugin perhaps)

stable spear
#

there is a default task scheduler which uses a thread pool, yes

#

I'm not sure if that exists in Unity, or if they disable it

hollow wing
#

๐Ÿค”

#

ok so to be sure I don't mess with the engine I should be using the plugin then?

#

hm it seems there are wide misunderstandings in the community

#

I consider the usage there wrong

unkempt nova
#

Coroutines are NOT threads

hollow wing
#

has nothing to do with coroutines (ok. got ya)

unkempt nova
#

Just reading the title, making sure you don't misunderstand that

#

Barely even related

stable spear
#

@hollow wing that guy is using UniTask, which provides async/await compatibility with Unity as well

unkempt nova
#

I've heard really good things about UniTask, but I don't understand what it provides that async doesn't

hollow wing
#

dude

hollow wing
#

it's so silly it's not in the beginning of the vid. (unless I didn't notice)

hollow wing
stable spear
#

next time you could just watch the whole video ๐Ÿ˜„

hollow wing
#

i could

unkempt nova
#

@stable spear I haven't messed with async/UniTask much. What does UniTask give you that async doesn't?

stable spear
hollow wing
#

but generally I don't think it's great watching a video that lacks the most relevant explanation in the beginning, til the end

unkempt nova
#

Ah, ok

stable spear
#

the default c# scheduler for tasks uses a thread pool

unkempt nova
#

Unitask makes it "threadsafe" then?

stable spear
#

yea. Plus it adds other goodies I'm sure

#

I've never used any of this

unkempt nova
#

That's kinda huge on its own, didn't know that

stable spear
#

so hypothetical

unkempt nova
#

Fair

stable spear
#

if you know there's something you can do from a thread pool safely

unkempt nova
#

Oh nice

flint sage
#

It's not that easy

#

Also TAP has real benefits over ECS

hushed fable
kindred tusk
flint sage
#

Task based async programming

kindred tusk
#

Is it a framework or a concept?

#

Oh this is just async/await in C#

#

I don't think asnyc and ECS are mutually exclusive.

south edge
#

any1 know how to change the elements from list by script?

sage radish
fallen halo
#

https://www.youtube.com/watch?v=xetW10MUI0o&list=PLy78FINcVmjA0zDBhLuLNL1Jo6xNMMq-W&index=26

In this vidoe bardent solved a problem at the 1 minute mark. The problem is superState causes a state change then the subState also cause another state change.
So bardent created a bool(isExitingState) that sets to true when ChangeState function gets called in the superState by putting isExitingState in the Exit function and checking that bool whether it is false only then the subState can do a state change. But he also put the variable in the Enter function which sets it to false. Like:

    {
        //other statements
        isExitingState = false;
    }

    public virtual void Exit()
    {
        //other statements
        isExitingState = true;
    }

    public void ChangeState(PlayerState newState)
    {
        CurrentState.Exit();
        CurrentState = newState;
        CurrentState.Enter();
    }

But from the code above, if the super State calls ChangeState function it will first call the Exit function which will set isExitingState to true then it will assign the newState to CurrentState. But after that the newState's Enter gets called which will turn isExitingState to false.

Then when the subState checks for isExitingState it is found to be false and the substate can do transition again.
So in conclusion the problem doesn't gets solved.
So, what to do now

#

And is my assumption correct that the solution provided by bardent would not work

compact ingot
#

they won't save memory, as your data won't magically become smaller, but they are made and optimised for use with Jobs/Burst and will probably benefit from internal optimizations... i'd recommend profiling both and comparing. They are however slower than their unsafe counterparts which omit certain checks.

#

if you want maximum performance you'll have to look into unsafe pointers / memcopy / pinned memory / simd

kindred tusk
#

Which is faster?

#

That's probably right. It would be faster in burst compiler

#

Because you need to pass the data from C# to C++

#

But I think they're designed to be used in burst compiler, no?

half urchin
#

What is the best way to animate character with a lot of guns?

kindred tusk
half urchin
ember geyser
#

is there a way to create a thread and be absolutely certain it's not run on the main core of a CPU, that it's definitely offloaded to one of the other cores?

ember geyser
compact ingot
ember geyser
compact ingot
#

iirc this can however not be guaranteed, as it is ultimately delegated to the OS... its probably more reliable on a console platform than on a general purpose OS

ember geyser
#

iOS and Android my two main targets. So will be interesting to see how specific I can get about offloading to the other cores. Again... THANK YOU!!! I owe you beers, and bourbon, and whisky, and brandy, and cognac and armagnac.

compact ingot
ember geyser
compact ingot
#

i think they are used to strong opinions

ember geyser
compact ingot
ember geyser
# compact ingot the performance-crowd in general

Of all the folks that program, those keen on performance are by far the most fun to chat with, and the most normal. They're real, and care, and really care about the tangible output. I love them. Every one of them.

ember geyser
compact ingot
#

some profiling with burst on similar code to yours (array[i] = i)... do you get similar results?

Build:

TestNative    with n = 256, average runtime 0.000282 ms over 100 tests
TestNativeJob with n = 256, average runtime 0.000262 ms over 100 tests
TestGeneric   with n = 256, average runtime 0.000341 ms over 100 tests
TestNative    with n = 524288, average runtime 0.966340 ms over 100 tests
TestNativeJob with n = 524288, average runtime 0.132264 ms over 100 tests
TestGeneric   with n = 524288, average runtime 0.193129 ms over 100 tests

Editor

TestNative    with n = 256, average runtime 0.007643 ms over 100 tests
TestNativeJob with n = 256, average runtime 0.009305 ms over 100 tests
TestGeneric   with n = 256, average runtime 0.000673 ms over 100 tests
TestNative    with n = 524288, average runtime 16.096659 ms over 100 tests
TestNativeJob with n = 524288, average runtime 18.368747 ms over 100 tests
TestGeneric   with n = 524288, average runtime 1.265214 ms over 100 tests
minor girder
slate stratus
#

hi there, is there a way i can disable unity's render pipeline completely? i'm trying to have an asset bundle render in -batchmode but i don't want to have the application run at whatever speed. I wanted to be able to step through the frames manually; something like this would make sense:

Start() {
LoadBundle()
}

int step = 0;
void Fixed() {
  Camera.rotate(step); //example code
  Camera.takePicture();

  step++;
  if(steps > 20)
    Application.Quit();

  NextFrame(); // this is primarily because i really don't have the graphical processing power to just let the application do whatever it wants on my server
}
exotic ember
#

how i made a key door sys, pls help

daring pelican
#

I am making a bunch of scripts that I could swap out to change the method used for moving an object (i.e. MoveTowards, Lerp, etc.)

#

I want to make it super nice and easy to use, so right now I can type Movement.Move(Destination, Speed)

#

Where Movement is the base abstract class

#

And its children implement Move(Destination, Speed) method

#

What do you guys think of this? You think I could make it even easier to call that method? Or the way I am handling this?

kindred tusk
#

It sounds like you want to disable Update, not the render pipeline

#

@slate stratus are you not able to just do an editor script?

slate stratus
#

i'm building a unity standalone player that takes an asset bundle and renders the object inside of it (takes pictures of it around the object) and then moves on
but ideally i want to make it do nothing but render that one object, no particle sources, audio or anything, so i can get the most performance out of a single GPU/server that I can

kindred tusk
#

I just realized, you don't need to disable Update, just do everything in start and then quit

#

You'll complete your operation before the first update

slate stratus
#

would it re-render the scene without going into the next frame?

kindred tusk
#

Re-render?

kindred tusk
#

It will execute the code that you write in start

#

If you don't want any particle effects then don't include them in the scene

slate stratus
#

right now it produces an output like this from the standalone player

kindred tusk
slate stratus
kindred tusk
#

So you do want particle effects?

slate stratus
#

no, i want to render the images without anything but the GameObject in the assetbundle and it's textures without anything else,

#

i've disabled all animations by going through all the gameobjects that are children of the main gameobject

#

but ideally i want to make it not use any other resources while it can, because the standalone player has limited resources available on it's server

kindred tusk
#

Then destroy all particle effects after spawning the object

#

Yeah, unity is not good for that. It comes with everything

#

Project tiny is their exploration into a more modular system

slate stratus
#

it's trying to run in play mode at a target framerate of whatever (each frame is an individually rendered image) which is far too heavy and overperforming for the server

kindred tusk
#

You don't need a frame rate

#

It's not a real time application

slate stratus
#

if i set targetFramerate to 1 it does one image per second

#

yeah exactly

kindred tusk
#

Just do it in a loop

slate stratus
#

in start?

kindred tusk
#

Sure

#

Wherever

slate stratus
#

i'll try

kindred tusk
#

Start, awake, update

#

It doesn't make a difference

slate stratus
#

i want to disable all the unnecessary features of unity somehow so i can push the most juice out of this small server

#

but yeah i'll try that

#

is there a way we could have the camera still render something even with -nographics?

kindred tusk
#

You can disable physics

kindred tusk
#

I seriously doubt it

#

Since you want graphics

slate stratus
#

yeah i'll try something

kindred tusk
#

I mean usually with these things it's cheaper to just pay for a beefier server than more developer time

#

Unity is not a light weight piece of software

#

If project tiny hasn't been abandoned it might be worth looking into if you really need it

slate stratus
#

yeah i'll try looking into it

#

i may just try disabling useless functions from a winapi level

kindred tusk
#

Nah looks wrong

#

I doubt it could load generic asset bundles

#

I just read the short description

long ivy
#

did you test with the safety and type checks enabled in the editor, or in a build?

modest lintel
#

I don't think Project Tiny even supports asset bundles

slate stratus
#

@kindred tusk your idea worked, thank you.
if i had an infinite while loop in the start function, would there be an issue?
i have no logic in the Update() function at all or any other functions

modest lintel
#

You mean as a coroutine?

slate stratus
#

kinda

#

i'll show you what the code i have

modest lintel
#

That'd just crash, you don't have a yield inside the while loop

slate stratus
#

well this code worked just fine now

modest lintel
#

Depends on the number of steps.

#

12 is fine. ~200+ is not (arbitrary figure)

slate stratus
#

i was just wondering if i could have something like this

while(true) 
{
  var avatar = GetNextAvatar("https://myapi.com/render"); // downloads the asset bundle and related details to render for the customer
  Render(avatar); // calls the code that you see in the pastebin, since that one was just a prototype
  UploadAvatarImages(avatar.Id); // uploads it back to my server for a preview
  Wait(1000); // waits a little bit before asking for the next avatar
}
long ivy
#

why make this a coroutine at all? You can manually render the Camera (which you're doing)

slate stratus
#

ah i see

#

yeah i am

#

something like that

#

not sure if i could have that infinetely go into the Start() loop, assuming it'd crash eventually

kindred tusk
modest lintel
#

Why wouldn't it? If they have like....500 steps

#

Technically it'd hang but ๐Ÿคทโ€โ™‚๏ธ

kindred tusk
#

Well it wouldn't hang either, it just wouldn't render a frame

#

It would do what they intend

#

You may not have read the above discussion

slate stratus
kindred tusk
#

No don't do that

slate stratus
#

something like this

#

RAvatar() works in start, and does exactly what i desire

kindred tusk
#

If you do that you'll be rendering frames for 1s between

slate stratus
#

RAvatar renders 12 images*

#

and then finishes

kindred tusk
#

But if you use sleep you'll guarantee no code is run

slate stratus
kindred tusk
#

It will block the main thread

slate stratus
#

this makes more sense

#

hm.

modest lintel
#

Erm, I read it again just now. Still not seeing why it wouldn't timeout?
Unless the idea is basically ignore the frame rate, do one image per frame?

kindred tusk
#

Which is what you want, right?

kindred tusk
#

There is no timeout

slate stratus
#

essentially
void start {
var nextToProcess = GetFromOnlineQueue()
if(nextToProcess is not null)
then process it
otherwise wait a couple seconds
repeat
}

process {
rotate object
take picture
if rotations exceed 12
then stop and send pictures up in new thread
}

#

is what i'm trying to do

modest lintel
#

lol, I think I'm confusing myself with old assumptions, I'll step out while you two solve this ๐Ÿ™‚

slate stratus
#

a player that sits in a loop waiting for new assetbundles to render from a server

kindred tusk
#

You can have an infinitely long loop in unity

#

That's what the hang is

modest lintel
#

Well, if I run a loop of 2000 debug.logs, unity crashes

#

So, I assume there's a timeout where the hang is considered a application error

kindred tusk
#

You mean "has stopped responding"?

modest lintel
#

Yeah

kindred tusk
#

That's not a crash

#

If you wait the program will resume

slate stratus
#

if it's unresponsiveto winapi's pings

kindred tusk
#

But you're running this on CLI right?

slate stratus
#

yes

#

a daemon will restart it if it crashes

kindred tusk
#

Windows or Linux?

slate stratus
#

windows most likely

slate stratus
kindred tusk
#

I wonder if that same check applies to headless

#

Well easy to check

slate stratus
#

i want it to be able to load and render the asset bundles~ in under a second and push the images up

kindred tusk
#

You could always yield a single frame every minute

#

If you needed to get around it

slate stratus
#

the network throughput is 50gbps so the assetbundles will load quick enough

kindred tusk
#

But I think that whole not responding thing is part of the window manager

slate stratus
#

yeah it is

#

not sure, only one way to test

modest lintel
#

one'd think there be more links on how to make a hung application not close on itself ๐Ÿ˜›

slate stratus
#

lol

#

is assetbundle loading single threaded?

kindred tusk
#

I just realized that if you do it this way in editor you won't be able to stop it

slate stratus
#

yeah i know

kindred tusk
#

Honestly I think you should just do it the normal way and throw more money at your server

slate stratus
#

:/ can't offload the cost of that

kindred tusk
#

Just disable the camera

slate stratus
#

then we can't render transparent images

kindred tusk
#

Why?

kindred tusk
slate stratus
#

the bandwidth is free

#

the cost of processing is far more than that

#

we can throw beefier money to the servers but ideally i want to make it as fast as possible, the more money saved the better

kindred tusk
#

How slow is it?

slate stratus
#

well, average laptop hardware takes well over 5 seconds to render a single bundle

#

my 3090 does it in under a few ms

#

decompressing and loading the bundle is extremely fast because the CPUs are fast, the GPUs are dated hardware (e.g. 750tis and are virtualized)

#

i can try to do the while loop like you said so long as the unity project doesn't close itself out

kindred tusk
#

Brutal. Have you profiled it?

slate stratus
#

not yet, how would i go about doing that?

kindred tusk
#

Open the profiler and hit record

slate stratus
#

oh i see

kindred tusk
#

You'll need to be doing it frame-by-frame to see

slate stratus
#

i just used the standalone player and used a stopwatch to time it

kindred tusk
#

Where the costs lie

slate stratus
kindred tusk
#

But that won't tell you what is using the time

slate stratus
#

and made this

kindred tusk
#

If it's the rendering itself you're SOOL

slate stratus
#

the most heaviest call is loading the asset bundle for the first time and taking the first screenshot

kindred tusk
#

Maybe first screenshot initializes stuff

slate stratus
#

assetbundle loading is probably decompressing the LZMA archive, however on those offloaded server CPUs they will perform better than this

#

but those ~54ms screenshot calls if I could somehow speed them up which i did from your suggestion of putting this all in the start loop

#

instead of taking ~90ms per screenshot and ~800ms to load bundle, these are the new numbers

#

which is an improvement in it's self and pretty scalable imo

ashen linden
long ivy
ashen linden
#

I imported it too
using Parabox.CSG;

#

on autocomplete it only shows Parabox.CSG.Demo

#

there's nothing else than it at Parabox.CSG

untold moth
#

Check one of the closed issues in the repository.

urban warren
ashen linden
#

actually i don't know how to do that

untold moth
#

If you don't use assembly definitions, deleting their assembly definition file might work too.

ashen linden
#

now it can't even find Parabox namespace

untold moth
#

Then perhaps there are more than 1 assembly definition.๐Ÿค”

#

Hmm... Doesn't seem so. Try refreshing and reopening your ide.

ashen linden
#

There was one more i think, i deleted it and it works now. Thanks

urban warren
ashen linden
#

i've just found out it wasn't what i was looking for :D

bright geyser
#

In python, I have the following definition, can anyone tell me what this means in c# please

class ODESolver(Enum):
    SemiImplicit = 0
    Explicit = 1
    RungeKutta = 2```
austere jewel
#

I don't know python but that says enum

#

so I would assume it is one

bright geyser
#

so just a series of enumerations

austere jewel
bright geyser
#

cheers

pulsar isle
#

Any guidance on how to extract each frame in video and put it into a List<Texture2D> ?

kindred tusk
#

If this is just running on a machine you have access to you might consider using ffmpeg.

#

You might even be able to bundle ffmpeg with your program.

storm maple
#

Hey guys, don't know where to really put this so imma ask it here:
I want to have a bunch of sprites in my 3D world, and they need to be billboarded - look at the camera always - but not in such a way that i have to update their transform every single frame

#

simmilar to particles

#

correct me if i'm wrong but updating the transform a bunch of times is costly

hushed fable
#

You could use billboarding shader.
Unity should handle transform modifications pretty decently, especially if the transform you are modifying isn't part of some more complex tree of transforms.

storm maple
hushed fable
#

Something like, probably.

#

Not a shader person ๐Ÿ˜„

storm maple
#

Ok thank you :)

finite pond
#

I'm setting a SpriteRenderer's size through a UnityEvent directly after Instantiating a prefab. Debugging shows that the SpriteRenderer's size is indeed being updated correctly. However, in-game, the size is reset to (1, 1).
Is this a bug in Unity? I'm definitely not setting the size again after the UnityEvent, I've set a breakpoint in SpriteRenderer's size setter.

#

It does work if I delay the setting of the size by 2 frames with a coroutine (but not 1!), but that looks off as the player can see the sprite being resized.

#

That makes me believe unity sets the SpriteRenderer Size to (1, 1) in Start() or some other initialization step?

lone elk
#

Anyone encountered crashes while attempting to modify some spriteRenderers? Code in question:

void Start()
    {
        _particleSystem = GetComponent<ParticleSystem>();
        if (_particleSystem == null)
            _particleSystem = Utility.FirstChild(gameObject).GetComponent<ParticleSystem>();

        ParticleSystem.ShapeModule shape = _particleSystem.shape;
        temp.spriteRenderer = gameObject.GetComponentInParent<SpriteRenderer>();
    }

(crash happens at temp.spriteRenderer = ...)

sly grove
sly grove
#

I'm assuming it's one of the particle system module structs, yes, but it's not defined in this code snippet

#

that is a field on some of the Particle system modules, including the ShapeModule

#

but the code isn't showing where temp is declared and assigned

#

I'm assuming there's some typo here:

        ParticleSystem.ShapeModule shape = _particleSystem.shape;
        temp.spriteRenderer = gameObject.GetComponentInParent<SpriteRenderer>();```
#

like the second line should be using shape not temp

#

Maybe the error is due to this - he's using an uninitialized ShapeModule by accident or something

#

@lone elk

#

also not really sure if it's possible to just assign a SpriteRenderer to the ShapeModule like that? But I'm not sure

regal olive
lone elk
finite pond
static lark
#

I'm coming from python, Linq is breaking my brain. I have a list of myList<myClass> and I want a function which is passed to a method which then sorts a list based on a sorting delegate method. Pseudocode below to maybe make it more clear

public class myClass{
  public int getParam1(){"gets an int"}
  public int getParam2(){"gets a different int"}

  public List<myClass> myList; 
  
  public void OrderList(?delegate?){ /////How do I write this line and initialize the delegate?
    myList.OrderBy(delegate);
  }

void OnEnable()
  {
    OrderList(getParam1); 
  }  ```
gray pulsar
carmine ermine
#

you dont really have to pass in a delegate, you can write it right there and then

static lark
gray pulsar
#

I'd expect it to look something like this.

public void OrderList(Func comparer)
{
  myList.OrderBy(comparer);
}
static lark
urban warren
#

You should look up delegates, Func, Action, and lambda

static lark
#

I understand actions and lambda functions. This wouldn't work with lambda functions and actions are just delegates with no return value and some boilerplate code removed from them (from what I understand) But actions are a simplification of delegates

gray pulsar
static lark
#

thx guys, I'll see what I can find

carmine ermine
#

^

urban warren
#

What are you guys opinion on using local functions, and if you use them how do you separate them visually from the body of the method?
I tend to put them at the bottom after the return (if there is one). But I find that it makes the method a bit harder to read than if it was a stand alone method.

gray pulsar
# urban warren What are you guys opinion on using local functions, and if you use them how do y...

I've gotten into the habit of writing functions inside of functions in C#. It's nice, because you can write bespoke one-off functions without littering the class. And you can use variables from the parent scope. Any reason it might be a bad idea? It does feel like cheating.

Likes

392

#

(I have no opinions of my own, but this thread was interesting)

urban warren
native cipher
#

Can I define custom collider? I have custom raycasting algothithm

urban warren
native cipher
#

nah, not an option. The "mesh" is driven on gpu

urban warren
#

Idk if PhysX supports it, but maybe you could write a C++ extension for physX with your custom shape which you then compile to a library and add as a plugin to Unity.

#

This is just an idea off of the top of my head, no idea if it would actually be viable, but I can't think of any other way to do it.

soft copper
sly grove
#

You can of course do whatever you want in your code, but you can't make Physics.Raycast detect your custom collider. You can write your own raycast method that does it though

sly grove
native cipher
#

yeah, it may be possible to "wrap" physics object (or at least character controller) with wrapper script that would stop rigid bodies from moving through.

#

like applying force in direction of the normal

subtle river
#

Howdy, all ๐Ÿ‘‹ I'm doin some video streaming and the api I'm using provides you an intptr for the raw texture data.
loading it into the texture works ezpz

texture.LoadRawTextureData(data, width * height * 4);

but I'd love to generate mip maps for the texture so it looks nice. i know I could write some janky code that uses one texture for the raw data and another for copying the pixels and generating the mip maps, but I'm interested if there's a way to use a single texture. (this has to work for dozens of streams, so i don't wanna spend a ton of time doing unnecessary memory juggling)

i can make a new texture like so, and pass true for allocating memory for the mip chain

texture = new Texture2D(width, height, TextureFormat.RGBA32, true);

but when I load in the raw, unmipped texture data, unity throws an error since it wants the raw data to include mips

// does not work if mips are enabled
texture.LoadRawTextureData(data, width * height * 4);

Would be lovely if the api let you load raw data for the source texture and have unity generate mips for it. does anyone know if there's a clean way to handle mipping dynamic texture data

urban warren
urban warren
sly grove
#

Thing is I don't really understand how they even prevent clutter. They take up just as much space in the file, except they're an extra indentation level and ruin the whole flow of reading the class (so actually they may take up more lines just for that reason). Just my opinion.

urban warren
soft copper
#

Huh, you learn something everyday I suppose

compact ether
#

So, I have a question that is saving related, and I'm not even sure if my game has a bug or not.
So my game saves information based on ints. If you reach a certain score, the script sets the int value for that level, and if it's over the target score, you unlock the level.
Simple enough, right? My question is really silly, but, how do I make sure when I make a build of my game, that it isn't bringing any of that saved data with it?
I put my game up on Itch, and I think I accidentally uploaded the file that has the entire game beaten already haha.

#

Also, I wasn't sure if this was the appropriate channel for this, but I figured a more advanced dev would be more familiar with it.

subtle river
#

Depends on how you're saving the data. If you're using player prefs it won't be copied with builds since save data is stored in windows registry/plist

compact ether
subtle river
#

yup!

kindred tusk
compact ingot
kindred tusk
#

The "clutter" is namespace clutter @sly grove, not visual clutter. When you're autocompleting methods elsewhere in the class. You can also define inner methods in places where their pre-conditions are already met, making naming and guarding simpler.

echo holly
#

does anyone know if its possible to use unity's orange outline in editor to outline other stuff for editor tools?

ember geyser
ember geyser
#

I'm not arguing against, it, genuinely curious. I've used Blocks in Objective-C, and can see how they're useful, somewhat. Pedantic, but sometimes useful. To my mind, "closures" in C# are just Microsoft acting as though they want to keep up with the other cool languages.

#

and there seem, to me, to be way more traps possible with => that are easily fallen into, that it's safer to not ever use the thing, unless you fully understand all the ways it can generate garbage and/or do other unwanted things.

frozen imp
#

Among other things local functions provide graceful way of escaping nested loops avoiding goto usage.

cursive horizon
#

I donno if I fully agree, but Brian talks a little about when he uses local functions in this classic (timestamp, it's a couple minutes of the video):
https://youtu.be/QM1iUe6IofM?t=2235 (Brian Will - Object-Oriented Programming is Bad)

Basically, it's nice to be able to keep long sections of procedural code procedural, but also have clear scopes within that code, as well as be able to 'return' from sections of it in a way that's tricky otherwise (like Fogsight said).

kindred tusk
#

I'll try to find an example

#

Here's a couple of examples of where I've used one:

Deduplicating a code path that's called twice with different inputs:

    IEnumerator CaptureScreenshotCoroutine(Texture2D texture, Action onComplete) {
      void SetCanvasEnabled(bool isEnabled) {
        _rootCanvas.enabled = isEnabled;
        if (Dialog.TryGetInstance(out var dialog)) {
          dialog.IsCanvasEnabled = isEnabled;
        }
      }
      SetCanvasEnabled(false);
      yield return new WaitForEndOfFrame();
      texture.Resize(Screen.width, Screen.height);
      texture.ReadPixels(
        new Rect(0, 0, Screen.width, Screen.height),
        destX: 0,
        destY: 0,
        recalculateMipMaps: false
      );
      SetCanvasEnabled(true);
      texture.Apply();
      onComplete();
    }
#

A code path that is called with a variety of conditions, but not in all cases:

      void Speak(int syllableCount) {
        var c = _characters[_selectedCharacterIndex];
        c.MoveHead();
        c.BurbleOverride.EmitSyllables(syllableCount, null);
        c.SetIsSpeaking(true);
        _stopSpeakingAt = Time.time + syllableCount * c.BurbleOverrideConfig.SyllableDuration;
      }

      if (Input.GetKeyDown(KeyCode.Q)) {
        Speak(1);
      } else if (Input.GetKeyDown(KeyCode.W)) {
        Speak(2);
      } else if (Input.GetKeyDown(KeyCode.E)) {
        Speak(3);
      }
#

Deduplication, but for code that should only be called from an initialization method:

      // Ensure singletons exist.
      void EnsureSingleton<T>(T prefab) where T : Singleton<T> {
        if (!Singleton<T>.TryGetInstance(out _)) {
          Instantiate(prefab);
        }
      }
      EnsureSingleton(_demoManagerPrefab);
      EnsureSingleton(_displayManagerPrefab);
      EnsureSingleton(_optionsManagerPrefab);
      EnsureSingleton(_buttonIconManagerPrefab);
      EnsureSingleton(_faderPrefab);
      EnsureSingleton(_dialogPrefab);
      EnsureSingleton(_persistentVariableManagerPrefab);
#

Creating a test-specific assertion that needs to capture outer scope:

    [Test]
    public void MementoDescriptions() {
      var errors = new List<string>();
      void AssertPresent(string text, string message) {
        if (string.IsNullOrWhiteSpace(text)) {
          errors.Add(message);
        }
      }
      foreach (var memento in GetMementos()) {
        AssertPresent(memento.Title, $"Memento '{memento.Id}' has no title");
        AssertPresent(memento.Trigger, $"Memento '{memento.Id}' has no trigger");
        AssertPresent(memento.Description, $"Memento '{memento.Id}' has no description");
        AssertPresent(memento.Clue, $"Memento '{memento.Id}' has no clue");
      }
      Assert.IsEmpty(errors, string.Join("\n", errors));
    }
kindred tusk
kindred tusk
ember geyser
ember geyser
ember geyser
ember geyser
# kindred tusk I think you might underestimate the value of closures if that's the case. People...

I don't use delegates, at all, because of the garbage creation. So I'm not normal. And a bit odd, too. But I understand exactly how and why delegates can be useful, just that garbage is a cost I can't stand. So I've learnt just enough OOP to make state objects, and swap them in and out with abstracts guiding their ability to respond. Otherwise, I completely agree with you, delegates are mechanically significant, just too wasteful of precious time for me.

ember geyser
kindred tusk
#

You're welcome!

kindred tusk
# ember geyser I don't use delegates, at all, because of the garbage creation. So I'm not norma...

There is no difference in using these objects to delegates. The heap allocation only happen on creation (just like if you did new MyEventHandler()). They won't cause GC unless you're losing the reference. So if you just create an event handler delegate at startup and keep it there forever it's going to be the same, just as it would be a problem to do new MyEventHandler() each time you wanted to handle a new callback.

(Assuming a Java-style class MyEventHandler : ICallbackInterface)

ember geyser
#

I don't know Java, and barely know C#. I use it like it's C plus a lot of work to avoid C#

kindred tusk
#

Well, C has function pointers and C++ has delegates

ember geyser
kindred tusk
#

"pointers to functions" are actually delegates and also cause heap allocation

ember geyser
#

And once I learnt about how to bottle state in objects, and swap out the objects with abstract overrides, I completely threw away any notion of ever using delegates ๐Ÿ˜‰

kindred tusk
#

i.e.

void X() {
}

void Start() {
  someObject.SomeEvent += X; // X is wrapped to capture its `this` and causes an allocation.
}
ember geyser
#

if you use it like that, yes, it probably is exactly like a delegate. It even looks like it.

kindred tusk
#

Ah yeah, burst compiler is its own beast. I don't know much about it.

tropic lake
#

i think it'd need things like static helper classes to contain pure functions because you can't have standalone functions in c#

cursive horizon
#

but i also find that my game code doesn't actually have those big blocks of procedural code, so ๐Ÿคทโ€โ™‚๏ธ

tropic lake
#

what i don't like about static helper classes is that you want to avoid giving names and grouping things together, but classes sort of force that anyway

#

unless you have one large static class and put every pure function in it

cursive horizon
#

Utils ๐Ÿ˜„

#

on some level you are always doing that

#

what do you name the file that you store your functions in?

#

but yeah, ultimately they are just global functions organized into categories, which i think can be good for some things but probably not most things

tropic lake
#

trying to do procedural code just feels like working against the language and engine entirely

#

so at that point is it really worth it

#

but then again you could always just go a little bit procedural and a little bit object oriented

#

mix it up

cursive horizon
#

right, it's all tradeoffs and in some situations it's worth it

#

that's sort of what ECS is though

#

you organize your big procedural functions into 'systems' which then act on data entities

compact ingot
#

and this is also possible ad-hoc, without any extras like ECS

tropic lake
#

one sentence???

#

i waited this long??

compact ingot
#

all the time, everywhere

tropic lake
#

yeah idk if i want to jump into that can of worms

#

i'll stick with OO and trying to procedural-ise it as much as makes sense

cursive horizon
#

it depends on your game, but for me a mixture has ended up working best

tropic lake
#

cool video tho thanks for sharing

cursive horizon
#

trying to force everything into ECS can get real weird, just like forcing inherently flexible/dynamic/cross-cutting systems into OO can get real weird

#

if you can make something simple and self contained like OO promises, that can be really nice

tropic lake
#

yeah and i think game development isn't exactly like other software development

cursive horizon
#

but for some things it's tough to do that, and in those cases you can flip the paradigm and have your objects be 'dumb' with data components attached, and then read those components elsewhere and do stuff with them

tropic lake
#

best practices for programming won't always apply

cursive horizon
#

definitely

#

often 'best practices' are about drawing hard boundaries to simplify complex systems into smaller chunks

#

if you can architecturally limit possibilities, there's a lot of value in that

#

but in games, you sort of want everything to be able to interact with everything else

#

not always, in all contexts, because then your program is a nightmare

#

but certainly much more than some CRUDy web app

compact ingot
#

and you have much more/deeper interaction with non-tech people that are critical to success

cursive horizon
#

for a game i'd often rather have a convention than something the compiler enforces, because i might want to be able to do that weird thing later, and i can enforce conventions at the 'config' layer rather than limiting my game code at the 'engine' layer...if that makes any sense

cursive horizon
#

aye, it should be required watching after a couple years of programming

#

if only so that people can stop feeling bad about themselves for failing to fit everything into perfect hierarchies

kindred tusk
#

Or feel worse about it

slender wolf
#

(is it okay for me to abruptly ask a question right now?)

untold moth
slender wolf
#

Alright, quick question, I have been getting an odd error using Unity 2017.4.22f1 and .NET 3.5 (for modding purposes) with my own class library as a plugin.

Here's a simple model of said class library.

public class A<T>
{
    private T _value;
    
    public ref T Value => ref _value;
}

When I try to instantiate the class, it causes an error on the console and points to the line of the constructor.

error CS0584: Internal compiler error: The method or operation is not implemented.

As far as I can tell, Unity doesn't like it when a method signature specifically has a return value of a reference to a generic. I suspect this is something to do with Mono.

Does anyone know why this is the case? I don't really know how reference return values get compiled. Obviously shoving newer features in older versions is bound to fail, but this seems extremely random to me.

#

To repeat, changing the generic to string for example, or really any other type suddenly makes this work fine.

#

Removing the ref from the method signature makes it work with the generic, even if I use ref locals in the method.

#

(technically properties are methods anyway)

untold moth
#

Did you try adding parenthesis?๐Ÿค”

#

public ref T Value() => ref _value;

#

Ah, wait. That's just a propery

slender wolf
#

Yeah, it compiles as get_Value when using a property.

#

I did try both, it doesn't work either way.

cursive horizon
#

i just copied it into my project and it seems to compile fine

#

unless i'm dumb

slender wolf
#

You used the same version, used this code in a class library, and tried instantiating it in a script?

#

This should work on later unity versions, but I'm unfortunately stuck on 2017.4 with a really old framework.

cursive horizon
#

ah gotcha

kindred tusk
#

You can return ref in older versions of C#

#

I think it's C#7 or something

slender wolf
# kindred tusk I think it's C#7 or something

Correct, it was introduced in C# 7.0 according to the documentation. The confusion I have here is that the class library (which has version preview/10) compiles as normal, and loading it in Unity is fine until I reference the class containing a reference return value of only a generic.

kindred tusk
#

Speculating a bit here.

#

Whereas the contents of the DLL will otherwise be precompiled bytecode.

slender wolf
#

Oh right, maybe it could be that simple.

#

What I am wondering though is whether this is C#'s, .NET Framework's, Mono's, or Unity's fault.

flint sage
#

What unity version are you on?

slender wolf
#

2017.4, naturally upgrading would make this work, but I require this specific version for modding a game. @flint sage

#

By the sounds of it, it really does sound impossible to find a sneaky way around this issue.

flint sage
#

Yeah that sounds like an issue with the mono runtime not supporting that specific feature

#

It's weird though that it only happens once you reference that class, I guess you found one of those issues where the runtime just breaks so badly ๐Ÿ˜…

slender wolf
#

Actually, let me see if I can find a patch note on Mono about referenced generic returns.

#

I couldn't find anything about it, though I'm sure you're correct.

#

Moral of the story if anyone runs into this obscure issue: Older Mono (presumably) didn't support referenced return values (though you can return a referenced value by-value), therefore workaround options are:

  1. Remove the ref keyword.
  2. Remove the generic.
  3. Upgrade to a future Unity version that supports this.
misty glade
#

I'm going to start the process of selecting a persistence framework for my multiplayer game and... I'm a little outdated (I'm a dinosaur who grew up on ODBC connections to oracle databases). Trying to wrap my head around the persistence/database technology changes in the last decade or two is overwhelming.

Anyone have any suggestions on how I can narrow this down or select a framework? Roughly, my requirements are something like:

  • I'd like to be able to de/serialize objects without writing a lot of SQL and code to do it manually. Best case is an API that's like "GetObject<T>(Guid Id)" and "SaveObject<T>(Guid Id, T obj)".
  • I need to write some tools to manage data easily (ie - web based back office for the designers/developers/support). I'd like that to be easy-ish.
  • I'd like to be able to do some reporting on the data. Nothing complicated, but I don't know what's easy/hard with this new NoSQL paradigm. Things like "what's my userbase DAU" or churn rate or LTV, etc.
  • I'd like to be cheap-ish (free?) to start. MS Cosmos looks good, but I'm told it's $$$.
  • Prefer MS/Azure/Github/Windows as a stack for integration reasons. Console app is C# windows, runs on an Azure VM currently.
  • Nice to have would be something that plugs and plays with something free like Postgres that I could upgrade later if warranted.

No idea how to research this. A day of googling just keeps pulling me back to Microsoft documentation/blogs/advertising.

kindred tusk
# misty glade I'm going to start the process of selecting a persistence framework for my multi...

Use PostgreSQL or MySQL (my pref is postgres)
Each supports JSON columns. Postgres has field-level queries for JSON. You don't need NoSQL if you put your unstructured data in this column type.
Metabase is awesome for doing data visualization https://www.metabase.com/

#

wrt to hosting the database itself, I had an easy time using dokku w/ digitalocean

#

You can basically run a single command to provision a database on your instance

misty glade
#

Thanks Rhys. Do you recommend just starting with (uncompressed) JSON for all this? I don't really need querying on anything other than the Guid for now, but I imagine that long term... I might?

#

Cool. I've used DO before.

kindred tusk
#

Um... "uncompressed"?

misty glade
#

(JSON)

flint sage
#

Do you want a database or a game server as a service?

kindred tusk
#

Just put it in the database

misty glade
kindred tusk
#

@misty glade jsonb type is a binary representation of JSON that is supported in postgres. You'll need to use that if you want to query the object fields.

misty glade
kindred tusk
misty glade
#

Cool. Didn't know that was a thing.

kindred tusk
flint sage
#

If you just want a simple data store I'd just use a document store database

misty glade
#

I cut my teeth in an era before JSON existed.

kindred tusk
#

You can even index fields in JSON

flint sage
#

If your data is relational and want a little more effort you should use postgresql e.g.

#

I did, I'm giving options

kindred tusk
#

Ah, okay. I don't see why you'd use NoSQL when jsonb/json columns exist in a relational DB.

#

Personally.

#

But also metabase integration is a big win.

flint sage
#

If you didn't think about scaling your application at all, then pick a random database and it'll perform better than your server ikely

misty glade
#

Yeah, I mean, the data is a "little" relational but I don't want to spend the bulk of my time writing SQL and pulling out fields, new()ing up an object and populating those fields (and vice versa).. Not to say that I can't do that, I just feel like that's a huge amount of cycles to burn on busywork.

kindred tusk
#

It's not hard to transform a JSON object into columns -> value mapping.

#

You don't have to hand write every transformation.

flint sage
misty glade
#

Metabase - still reading their product pages - can it give me BI into things I haven't explicitly denormalized somehow? ie - if I have some "player" object with only the Guid key indexed.. could I do queries like "show me all players that have more than level 10"?

kindred tusk
#
function handleInsert(json) {
  const valid = pickKeys(json, permittedKeys);
  db.table("my_fun_records").insert(valid);
}
misty glade
#

(I wouldn't care about realtime performance for a query like that - I'd probably denormalize things that explicitly need to happen quickly during gameplay)

flint sage
#

And with GSaas, I meant things like Metaplay

kindred tusk
flint sage
#

And there's a bunch of other ones

kindred tusk
#

So almost certainly yes

misty glade
#

business intel

#

ie - figure out things like DAU/MAU, LTV, CPA (perhaps we have some integration with advertising spend or acquisition details)

kindred tusk
misty glade
#

"show me how many players churned out after earning this achievement" or something that's... related to the game objects

kindred tusk
#

Lots of PARTITION BY

#

wait... no.. can't remember the keyword now.

misty glade
#

"show me what percentage of my userbase has churned out after spending more than $1 in the store"

kindred tusk
#

Yeah, sure. You can do that

select count(*) from users group by spend > 100
misty glade
#

K. Moving over to back office tooling for a moment - are there frameworks or tools that I could stand up some administrator tools easily? again, preference is minimal implementation details. I would be happy with a tool that would allow "direct json editing" to begin with

kindred tusk
#

Although @flint sage's suggestion of an off-the-shelf game service is probably a good one.

misty glade
#

But better would be a tool that could allow me to generate/WSIWYG some sort of admin pages to edit data"

#

What are some common GSaaS products? Playfab..?

kindred tusk
misty glade
#

K. I mean, I don't mind writing the queries when I need to myself for one-off things, but I'm trying to think of a future where my game designers are supported. Basically we have a collectable game and the designers or that staff are going to need to edit some aspects of the content quite often.. Ie, "change this <thing> value from X to Y" or "make this <thing> available for four weeks before christmas" and I'm not quite sure how I'm going to support that yet. I know how I'm going to handle putting the content itself in a CDN (cloudflare) but.. making the logic/data available to the designers is a little hazy for me yet

#

Also support - "I bought this <thing> and it's not showing up in my account" or whatever

compact ingot
misty glade
#

That could be a solution, yeah

compact ingot
misty glade
#

I mean.. ideal is "bespoke admin tools" but I'd settle for "editable data with generated front end"

#

thanks, will check it out

compact ingot
#

Look at it, ask me anything about itโ€ฆ have been using it a lot lately. Will tell you all the bad stuff

misty glade
#

directus? or graphql

compact ingot
#

i have a library that can duplicate a directus api into a in-memory copy with plain c# objects that you can consume with any .net app โ€ฆ useful if you donโ€™t need updates while the client app runs

cyan jewel
#

Hi guys, just a small question. In my game i have a mechanic where coins can be dropped. On their first few seconds i want to make them so that the player cannot collide with them so they cant be picked up and then after a second or two they can be picked up. I already know about the 'IgnoreLayerCollision' function but the problem with that one is that there is no way to set the layers back to normal (i cant find a way to set them back to normal). Anyone got any ideas?

misty glade
#

call IgnoreLayerCollision again with the third parameter = false

cyan jewel
#

omds thank you so much, didnt know there was an overloaded method

misty glade
cyan jewel
#

i went to the docks and i only saw the function with just two parameters going in

#

oh thats not the one i saw, i just saw example code with two parameters going in

sly grove
#

there's only one version

cyan jewel
#

well regardless thanks

graceful zephyr
#

It seems my question was overlooked in general code so I'll instead ask it here.

I'm attempting to call to a list in a different class in the same namespace.
This is my code.

#

How can I do this? When I do, it says the list doesn't exist :>

#

Forgive me, after some more research I found using Public Static to create a list variable that I can access.

but It'll require some more tinkering to make work. Hopefully I get somewhere!

misty glade
#

You're declaring and initializing the list inside Start(). After Start() finishes, the list is discarded because it goes out of scope.

graceful zephyr
#

oh!
that actually says alot, should I make it its own class instead?
I recall a "Don'tdestroyonstart"
thing too...

#

Okay thanks a bunch, I'm sorry for asking in the wrong area, I haven't asked many questions.
I appreciate the help nonetheless!

misty glade
#

No worries

#

There's a lot of ways you can accomplish what you're looking for

graceful zephyr
#

you duh best โค๏ธ

misty glade
#

It really depends on the ... nature of what you're trying to do.

#

For example, one way might be to create a singleton game object with this script attached to it, then you could FindObjectsOfType<MySingleTon>() to get a reference to it

#

But since this looks like data, you might just want to have a static class, like you've done, and write some accessor methods like public string GetElement(int id) that simply look up the element in the list and return it

#

You don't need anything unity related for that - you just want a C# static class with a static constructor (google these terms)

graceful zephyr
#

That's exactly what I want, I just wasn't exactly sure how to do it.
I know most of the terms but I'll do a bit of googling to get it to work in my context.

This has been the most help I've ever had. I really appreciate it!

I've been fumblin around googling the wrong things.

so this clears alot up.

misty glade
#

If there's some sort of unlock mechanic, then you'll want a Player class with some sort of data structure to hold whether or not they can use that element

#

No worries.. just keep on fumbling and after twenty years you'll take up gardening like the rest of us

graceful zephyr
#

Hah, that's pretty inspiring not gonna lie.

#

I'm now going to save these message logs so I can go back to the advice you've given when I inevitably screw up

misty glade
#

No worries.. And just FYI these questions should probably be in beginner-code.. or.. ๐Ÿ‘€ the mods might get cranky. ๐Ÿ™‚

graceful zephyr
#

It'll be fine, now I know.
so I won't mess up next time :>

misty glade
#

(if no one answers just wait a while and reply to yourself and ask again.. politely) ๐Ÿ™‚

graceful zephyr
#

Got it :>

misty glade
#
  1. This isn't an #archived-code-advanced (or really even a #archived-code-general ) question... there's lots of resources on how to learn to program in C#. You'll want to google up System.Collections.Generic.List, foreach syntax, System.Math.Max or use Unity's math library.

  2. You probably shouldn't crosspost if you don't get an answer in 3 minutes.

graceful zephyr
#

Sharpings job is to say "It's a beginnercode question"
hah

misty glade
#

just saving the mods the work, right? ๐Ÿ˜›

graceful zephyr
#

I won't make the mistake again ๐Ÿ˜œ

floral kiln
#

thx

misty glade
graceful zephyr
misty glade
#

oh don't worry, you'll refactor this later and I won't have saved you anything ๐Ÿ˜‰ But in the meantime you'll learn all about ScriptableObjects, Singletons, data persistence, static classes, switch expressions, Dictionarys and more.

#

(again, depending on what you want to do) ๐Ÿ™‚

#

(all of those terms, btw, are really good reading for you at this point in your developer learning list, I think)

#

I'm assuming your player is going to have access to each of those elements during the course of your game?

graceful zephyr
#

I've looked into ScriptableObjects and Singletons, singletons seem a bit to complicated for what I'm trying to do, ScriptableObjects seem a biiiit closer to what I'm going for.

Dictionaries I understand and just, aren't what I need. Since I don't need the key.
but you are right!
alot of good stuff you've just taught me.

And close, I'm creating a magic game where using the first Four elements you can create interactions with the other elements.
so I'm trying to create as modular a system as possible to save me future headache.

#

I know there's like 144 billion interactions.
but I'm a masochist.
don't worry, I'll live through the pain

misty glade
#

If so - you'll want to take the bool (available) out of the Element class, since it's not an Element property, but a property of the relationship between your player and the element.

How I'd do that would be to have a Player singleton (it's not terribly complicated, and it's something you really should learn sooner rather than later so you can decide how to use it best and your code doesn't get to spaghet-ish) and a dictionary of bools with the element as the key. Some boiler code for you to get started:

public class Element // not a monobehavior
{
  static Element() { ... add all your items to the list ... }
  public static IReadOnlyList<Element> GetAllElements() { .. left as an exercise to the reader ... }

}

public class Player : MonoBehavior
{
  private Dictionary<Element, bool> _elementAccess;
  void Start()
  {
      _elementAccess = new Dictionary<Element, bool>();
      foreach (Element original in Element.GetAllElements())
      {
        Element clone = original.Clone(); // make a copy of the original - you don't need to do this, probably, but it's good to know where your data in memory "is"
        _elementAccess.Add(clone, false); // player doesn't have access to any elements 
      }
  }

  public void AddAccess(Element which)
  {
    _elementAccess[which] = true;
  }

  public void RemoveAccess(Element which)
  {
    _elementAccess[which] = false;
  }

  public bool HasAccess(Element which) => _elementAccess[which];
}
#

I cut a lot of corners in the above, and .. coding in discord is likely to generate some syntax errors, but hopefully that's close and gives you some stuff to chew on

#

and actually, i'm definitely doing some hand-wavey stuff between a static class and instance of a class, but.. if you go down that route and have trouble I'm sure someone can help (or I can, if I'm around)

graceful zephyr
#

handwavey.
what a way to explain magic.

Alright I'll go ahead and paste this into my notepad++ and pull it up on another monitor to just.
keep it all together and use it as kinda... a psuedocode!

I'm seeing some stuff that I was about to google too, so that's just amazing :D

misty glade
#

(and lol, I misspelled "Behavior")

graceful zephyr
#

I'm gonna use my brain hard

misty glade
#

๐Ÿ™‚

#

System.Collections.Generic.Dictionary and data structures (in general) should be high on your todo list

graceful zephyr
#

god gave me enough blood to use my brain so I'm gonna.
time to put it on the trello.

#

I'm glad I asked for help instead of fumbling

misty glade
#

Whipped this up to do a dialog box: https://pastebin.com/zQcV955t

It's got a panel (DialogBackground) with a click handler - clicking on this hides this dialog. It gets opened with a public Show() call. It has a panel (ButtonContainer) which scales up/down rapidly into place.

It works.. but for some reason, the animation is glitchy. I can't really describe it, but it appears to be dropping frames - sometimes the animation appears to complete before the ButtonContainer panel is shown. Is starting a coroutine immediately after/before SetActive() a bad idea?

Video attempt... might not really capture the stuttering. Watch closely when the panel opens. The green part seems to appear at the end of the animation coroutine.

#

In other words, I am currently:

  1. SetActive(true)
  2. Start the coroutine
  3. The panel that the coroutine pops out appears to.. snap into place at the end (instead of animating through the duration)
#

Nevermind, derp bug. Was setting gamObject.transform in the coroutine loop instead of ButtonContainer.transform.

plucky laurel
#

@misty glade oh wow, you have a general .net background?

#

i suggest you use a tweening library for that

#

DoTween

#

then it could be wrapped in a single call like panel.DOScale(finalScale, duration).OnComplete( ()=> buttons.interactive = true);

#

its a very weird way of solving this problem, using datetime, you typically work with Time.deltaTime and Time.time and their unscaled versions

#

apart from the datetime and ms thing which i will mentally ignore, the issue may be in the easing function

misty glade
#

I wrote my own tweening library actually because I wanted a bit more control over it all

#

i'm going to spend some time adding more easing funcs at some point since most of what I have is constrained from "min to max".. like I don't have any fun bouncy eases or "wiggles" at the end using damped numeric springing

#

I use the timestamp as a parameter because the.. real signature looks like this:

        public static float RangeMapF(float inValue, float inMin, float inMax, float outMin, float outMax, Func<float, float> easeFunc)

but I got tired of calling it with stuff like this:

                float currentX = TweenUtils.RangeMapF((float)ts.TotalMilliseconds, 0, duration1MS, start.x, end.x, TweenUtils.SmoothStop3);

So I made a little wrapper:

        public static float RangeMapF(TimeSpan ts, int inMin, int inMax, float outMin, float outMax, Func<float, float> easeFunc)
        {
            return RangeMapF((float)ts.TotalMilliseconds, (float)inMin, (float)inMax, outMin, outMax, easeFunc);
        }
#

(basically I just cast the parameters on the inside to floats and extract the milliseconds from the timestamp, which is like 90% of my use cases)

plucky laurel
#

this seems to be overengineered and

#

i dont understand the more control over it all , what control do you lack in DOTween?

misty glade
#

probably could have used DOTween, but I wrote this before I knew about that and .. it's worked for me shrug ๐Ÿ™‚

plucky laurel
#

i figured

#

imo its a bad attachment

wooden cedar
#

I like the approach of building it yourself to learn versus using some off the shelf tool.

ember geyser
# misty glade I wrote my own tweening library actually because I wanted a bit more control ove...

Very cool. Lot of good reasons to do it yourself! Try looking into AnimationCurve for your more complex tweens, as you can do AnimationCurve.Evaluate (time in 0 to 1) to make eases with very complex shapes, and it's quite performant, and light weight, and will drop straight into your little system. Saves you from doing complex maths to make complex curves, and gives you infinitely complex curves in the inspector.

plucky laurel
#

huh, wonder how many of you built their own tools for solved problems. navmesh, animation fsms, ui systems, sound systems, graphics systems, scene graph, physics library for good measure.

#

you all use them but its ok because it comes with the engine, but as soon as its not, there we go, reinventing the wheel, and looking down on "off the shelf" industry standard libraries that became standard for a reason

#

anim curves are supported in DOTween btw transform.DOMoveX(4, 1).SetEase(myAnimationCurve);

ember geyser
plucky laurel
#

why are you saying this?

#

its unrelated to the lib

ember geyser
#

Because you seem to be suggesting that it's bad to make one's own little tween library, because DOTween exists -> so I providing two reasons, but can provide dozens.

plucky laurel
#

those arent objective reasons

ember geyser
#

Garbage is objective!

#

Subjective reasons are still reasons!

plucky laurel
#

also you can grab a reference to the tween you created and control it indefinetly

ember geyser
#

Good for you. If you think it's great, use it. In my early days of using Unity, I made faster, lighter tweens, without any garbage, and got the control I wanted, and got to understand an enormous amount about how to use Unity WITHOUT coroutines. You want to argue with those reasons to write your own tweening, too?

plucky laurel
#

Yes ofc, since that mentality leaks into big projects, you end up with weird nonstandard solutions that are hard to maintain, and any new programmer scratches their head as to why is he forced to use it instead of something that is industry standard.

#

It hurts everyone, eventually, its good to learn, it leads to issues if you build on it.

ember geyser
green rock
#

if I have a state machine that passes variable between states (different classes), what would be the behaviour of the heap allocated members between those states? Will it be pass by reference or pass by value?

ember geyser
#

The best library for time, far and away, is MEC (more effective coroutines), but it's still got the coroutine problem.

ember geyser
plucky laurel
#

Its not a theoretical problem. It practical and present in a lot of projects.

#

What is the coroutine problem?

ember geyser
plucky laurel
plucky laurel
green rock
plucky laurel
#

Ok maybe not, you need to show an example

ember geyser
# plucky laurel You said you couldnt figure out the syntax and allocations, so i take it with a ...

and me not being able to figure it out doesn't mean I couldn't learn it by reading how to use it, watching a few videos and reading a few other sources. You've taken that far too far. Me not being able to figure it out gave me an insight into the manner and thinking of the creator - that he doesn't think like me, and therefore makes very different compromises and trandeoffs. That turned out to be true. You're making a lot of very strange presumptions.

plucky laurel
#

c# has rules for heap/stack allocation

#

in most cases in managed environment if its a class (extends object) it is allocated on the heap by default

#

those are called reference types, because they are always passed by reference

#

there are specific additional semantics on top of that where you could pass a value type by stack reference

plucky laurel