#archived-code-advanced
1 messages ยท Page 143 of 1
Whoa blast from the past
will that work with small amount of objects?
sure... just make the parameters smaller
(btw Anikki, I finished that refactor shortly after that conversation and .. man what a thrilling feeling)
anikki is the goat
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? ๐
Ah, I knew I saw something like that but I couldn't find it again. I will see if I can't understand how it works. Thank you.
(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?
how much do you want to control the initial state... are one move to victory situations allowed?
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
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
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
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
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..?
algo form a minute ago
oh, right
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
What don't you like about this approach? Looks good to me
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
oh, yeah, that's a nice optimization
so flip it around so it can never fail. Keep a list of open places. Every time you place an item, remove the selected open location and any adjacent location that would result in a chain
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])
well if efficiency is your goal, phrases like "try-placement" and "skip that efficiency step" sound odd to me
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
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
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.
so by fail case do you mean that you run out of open squares before you run out of items to place?
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. ??
Yeah, I could, but how often do I retry?
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
You can backtrack more than onceโฆ up to the first decision, discarding that whole tree of possible choices, then you wonโt ever run into an invalid configuration unless it is unsolvable from the start
Yeah, true
not sure but you would probably have to pin the rng sequence to be replayable
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
[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 ๐
https://pastebin.com/FAKKURiA final algo
there's probably some small optimizations in here but .. it's fine enough for now
Greetings gentlemen.
Anyone encountered problem when particle system just triggers randomly without any code referencing it? Actually, without anything referencing it?
https://gfycat.com/eagersentimentaliaerismetalmark
particle effects trigger automatically when instantiated i believe?
Activation OnAwake is turned off
i'm not an expert on them but when I was dabbling I vaguely remember having to set some property to auto play, off
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
that is odd.. and the prefab itself has play on awake = false?
i mean, i suppose it should
Not sure, sorry!
can we see the code?
Yeah, it is
Even scripts are turned off in prefabs
I know it's not how it works in programming, but it literally triggers out of nowhere
I've included some in the gif above
Give me a minute, I can send it here as text
there's no repeatable event that triggers it?
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
well there's two things going on that could be relevant. The Shake() and the Instantiate
is the particle system attached to the projectile?
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();
Shake is completely separate script for camera, it has no references as well
And no, Particles are not attached to projectiles, but to object that "shoots" them
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
I trusted this script to do only what it has to do
Big mistake...
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?
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
structs are, but arrays aren't. It's not complaining about the contents of the array, it's the array itself
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.
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.
This would be better in #โ๏ธโeditor-extensions, however not wrong in this channel. You can use EditorGUIUtility.GetMainWindowPosition() to get the width and height of the main window. I do not remember if this includes the X and Y, but I know it does not include the system widow header.
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.
and in combination with MechWarrior99's answer, the window you're looking for is an EditorWindow of type GameView. It's internal, so you'll have to use reflection to get it
I tried using GUIToScreenPoint, but it returned the same point, so I figured I have to read more about it to really understand what they mean by Screen Space and GUI Space in this context ๐ค
I hadn't found that EditorGUIUtility.GetMainWindowPosition() method, while it's not exactly what I want, it helps me get a lot closer to my desired result, thanks a lot!
Excellent! I think that's exactly what I was looking for, I'll try that
Thank you both @urban warren @long ivy ๐
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.
I customized the lego microgame, But how can i make it for mobile
I want to move jump in mobile but how?
How can I change sprite of each frame in a predefined animation at runtime with code?
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
the increment must be coprime with the set-size i.e. there must be no number besides 1 that evenly divides both, and yes, it is a magic number. best candidates are primes for set size and increment
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.
you need to parse your json into commands
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
probably in a separate class that you can reference wherever
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.
Partially, itโs not good designโฆ Iโd avoid it if possibleโฆ kinda necessary for type based editor stuff. Lots of issue with co- and contravariance
ah sorry, i am a little lost ๐ do you have an example ?
Check current discussion in #archived-code-general on composition
Alright, good to know I was right, thank you. I have tried looking up a good way to find a coprime of a number, but no luck. Best I have seen is comparing if two numbers are coprime. Do you happen to know a good way to get a coprime of a number? If not that's okay, you have already helped me a lot.
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
if STEP and N must be coprime while N can be any number then while N/2 < STEP < N holds, STEP can be any prime number and will be coprime to N... or in other words, pick any prime number less than N and greater than N/2... or even simpler, pick the greatest prime smaller than N.... i'd go for a prime that is close to N * 0.618... just to add another neat math property to the calculation
You keep editing it while I am thinking and getting ready to respond, and it keeps getting more helpful, haha.
What the heck is N * 0.618...?
golden ratio. 2 / (1 + Sqrt(5))
btw. there is no algorithm to find the "nearest" prime number that is any different from finding prime numbers in the first place...
Oh, I feel like a pretty advanced and competent programmer most of the time. But man does that feeling go away real quick when I need to do even slightly 'advanced' math...
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...
type 1.61803398875 into a calculator and press 1/x a couple of times... neatness... or you know when 161.8% of 61.8% of x = x
dont worry i feel you LOL
It doesn't appear to be doing anything 'special'? Just 'switching' between the two values?
the decimals stay the same which only happens for that number
this is glorious
golden ratio has a lot of special properties, including
- it is the only number who's square is greater than itself by one i.e phi^2 = phi^2 + 1
- it is the only number who's reciprocal (1 / itself) is less than itself by one i.e 1/phi = phi - 1
Neet! No idea how this is useful, but neet!
tree branches, on average are 360ยฐ * 0.618 offset from each other
in nature, the fibonacci sequence,
the length of all your bones in your limbs, relative to each other, e.g. in your fingers is 1:1.618
Fascinating.
also that... its the limit of the ratio of two consecutive numbers in the fibonacci series... which is something you have to implement 100000000 times when studying compsci...
yeah, the higher in the fibonacci sequence you go, the better of an approximation of the golden ratio you get
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
8 / 5 = 1.6
34 / 21 = ~1.619
144 / 89 = ~ 1.618
121393 / 75025 = ~ 1.61803399
why are you commenting every single line? totally unnecessary
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.
i see
It also looks kind of cursed tbh ๐
cursed is what C# IL looks like ๐
Fair enough, haha.
nah. you can easily make out everything in il
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
oh you don't wanna see LLVM IR code
even for a simple hello world program in rust it's like 200 lines
The assembly instructions are simple but still there's quite a lot about them to understand
i lied it's 614 lines
but most of it is not related to the code
or, it is in some obscure way
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
Lucky for us unity devs there's no need to write this
rust equivalent.. not so pretty
Rust is ugly enough by itself
damn
i think this looks rather good myself
apart from the whole <const N: usize> thing of course
No idea why they couldn't do a more C/C++ look with the addition of traits
well they at least did it good with generics
nobody who's seen templates is gonna say they look better
Well yeah that's kind of messy and gets wild real quick
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
how is it not a nice language
well, its hard to get it to compile ๐
ok fair
but that's one negative that adds a whole lot of benefits
for one you will never get data races
and the compiler is slow AF
I can't comment on that but C++ as well so you end up using cmake
"not nice" only really refers to the absence of convenience... not the language itself... its pretty neat
yeah it can be a bit slow when compiling larger applications, but most of that is just compiling dependencies, which you only have to compile once
So I've been told that it's neat but just looking at it makes me feel awkward
that's how i felt like at the beginning as well
havent personally done anything serious with it, only read the book and played around... everything else is 2nd hand
i get the same feeling, but at the same time, i like stuff like prolog & haskell although they continue to make me feel that way... maybe its just how convinced you are that it is nice that makes you ignore the feeling... i dont know
personally i don't know what people are talking about when they look at not so complicated rust code and are like ew
unfamiliar syntax
i guess but most of it is pretty similar apart from like... everything
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
they only tell you that C++ is dangerous because unsafe stuff
any rust programmer will recoil in horror at the mention of that word
unsafe is where the magic is
I like that unsafe space
since rust is centered around safety
also... safety and performance are kinda mutually exclusive
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
well with rust you get both ๐
in theory, and if you jump through all the hoops
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
maybe also forces you to change your way of thinking.... cant imagine a JS programmer adopting rust anytime soon
oh yeah
One thing I dislike about C# is the effort you have to do to keep memory use stable
total PITA
You get so used to sprinkle the new keyword everywhere
And relying on the garbage collector to help you
i find memory management (when you want to manage it yourself) in C# is WAY more complicated than in C++
It is
There are some gotchas though but they come with time
Still feels a bit iffy
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
Yeah it is, if you care enough to write some utilities yourself ๐
Do you know how to save a GameObject with the components on runtime? and load it when need it (for rollbacks)
custom save system, nothing built in
There's no out of the box solution that I know about
Hasn't anyone made something that works for Unity's default components yet?
there is no real general case that would allow anyone to make something that is really usefull
Your best bet is to look in the asset store
what would you consider default components?
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
i'd expect a generic solution to have the performance of C# implemented in python
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
would probably not be restorable because memory addresses have changed
Yeah good point, won't work with reference types
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...
You don't want to save gameObjects, you want to save POCOs and have good functionality to create/save the GOs from the POCOs
References are fine your serialization system just needs to handle it, ie serialize a ref to an ID then reverse on deserialize
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
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.
its a lot to explain end-to-end but i guess you are missing just a tiny thing before you can fill in the rest... so can you maybe describe what appears blurry to you?
Yeah, basically the architecture if I can call it like that? Like, where to put the parser, should it be a separate class or a part of other class, and stuff like that
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
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.. ๐
activate squiggly lines for violations and your OCD will take care ๐
heh
i've actually considered moving pretty strongly to TWAE, stylecop analyzers, etc
i think squggly lines do more for code cleanness than any book by uncle Bob
(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 ๐
we need AI that can differentiate between dogma and "hey this guy knows what he's doing"
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
i dont think these are violations, they have a pattern, make errors easier to spot
its also perfectly readable
exactly
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) ๐
its a desireable trait of a codebase to contain everything it actually does in one method... that's why in many cases I don't understand why people use classes as states in FSMs... i like that kind of overview you descirbe
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
if it does just that thing... i would not consider it problematic... i don't like jumping around in 100s of methods that all do the same thing basically
I recently .. refactored that from something where I did the one or two lines of "processing" inline, in the dispatch method
eg:
anything with a pattern collapses to one line of code in my mind
so i dont mind that at all
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
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
(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)?
you can do a semi formal proof of correctness, that is just as good
only if it improves something tangible, like debugging, iteration, later concretization
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)
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)
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
I don't think code should be written to cater to testing, but I do think that making dependencies explicit is valuable. That's my main critique of what you have there: you essentially have sets of mutations that you apply to your state, but each case is responsible for getting its data and applying those mutations, so there's no contract for what each actually requires
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)
I'm a little unclear how I could resolve that, though. Perhaps make the only public constructors for the mutations contain all the required elements? (which I can error check in the ctor)
i guess you are already kind of doing that, since this is resolving and creating the battle actions
yeah, basically
ad-hoc dependency injection
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
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)
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!)
right, I think I see what you're getting at
basically, as a rule of thumb, use only one . when accessing referenced data
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
OK.. that's a good idea, actually, minimizes the chance of accidental NREs
if you make the contract more specific, you can work within a more constrained scope (which is good here, i'd argue)
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
yeah, that's always the sticking point in games
(just playing devil's advocate - not sure if I personally believe that)
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
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
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)
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
Oh, that's good, actually.. the dispatch could send the entire battle but the "ability dispatch" could trim the fat
i actually think you are already doing most of that, but you could go further if you wanted
yep, keep narrowing it down
(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
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
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
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
valuable validators are valiable
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
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
in my experience they do it with a lot of pain and suffering on the part of people working on it ๐
haha
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
Are you trying to have state machines that contain state machines?
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?
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?
sorry, forgot to make it a reply to ping you. See above
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.
Is it valid to use tasks in Unity?
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
you're still talking about the package you linked I assume, correct? (as the plugin)
that is helpful
or any equivalent package, sure
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
using tasks is fine. Using tasks that you're running on another thread, you must be careful with
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)
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)
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
๐ค
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
The C# async / await workflow can simplify your code and give you more granular control over your game in Unity.
Learn how to convert your current coroutine workflow, what a task is, how to run sequential and synchronous code and how to return data from an asynchronous function.
UniTask: https://github.com/Cysharp/UniTask (Provides an efficien...
I consider the usage there wrong
Coroutines are NOT threads
has nothing to do with coroutines (ok. got ya)
Just reading the title, making sure you don't misunderstand that
Barely even related
@hollow wing that guy is using UniTask, which provides async/await compatibility with Unity as well
I've heard really good things about UniTask, but I don't understand what it provides that async doesn't
dude
thanks for resolving this lol
it's so silly it's not in the beginning of the vid. (unless I didn't notice)
it will probably not break your engine which was not designed for async, but I'm just infering that from what doxdust just said. and from the fact that it was designed for unity
next time you could just watch the whole video ๐
i could
@stable spear I haven't messed with async/UniTask much. What does UniTask give you that async doesn't?
Unity doesn't have a built-in safe way to run async/await tasks. UniTask provides that.
but generally I don't think it's great watching a video that lacks the most relevant explanation in the beginning, til the end
Ah, ok
the default c# scheduler for tasks uses a thread pool
Unitask makes it "threadsafe" then?
That's kinda huge on its own, didn't know that
so hypothetical
Fair
UniTask actually gives you a way to switch a currently running task from the main thread (PlayerLoop) to a thread pool:
https://github.com/Cysharp/UniTask#threadpool-limitation
kind of neat
if you know there's something you can do from a thread pool safely
Oh nice
Compatibility for platforms without threading, a.k.a WebGL. ๐
What's TAP?
Task based async programming
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.
any1 know how to change the elements from list by script?
Yes, you can ask about it in #๐ปโcode-beginner though
Jobs != ECS
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
Discord Server:
https://discord.gg/uHQrf7K
Git Hub Repo for this project:
https://github.com/Bardent/Platformer-Tutorial
Assets:
https://drive.google.com/drive/folders/1uPAk8JyDxEF_GYX7NnQrqr5qA_HKkMaf?usp=sharing
If you wish to support me more:
https://www.patreon.com/Bardent
The Bardent Asset Pack!
https://bardent.itch.io/the-bardent-asse...
And is my assumption correct that the solution provided by bardent would not work
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
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?
What is the best way to animate character with a lot of guns?
Not a programming question
Sorry bro
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?
custom scheduler?
I don't know what that means. Sorry!
https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processthread.processoraffinity?view=netstandard-2.0 you could use that in a custom scheduler to kinda make sure that the main thread remains untouched
oh.... NO! that looks EXCITING.... I'm going to lose much time down that little rabbit hole. THANK YOU!!!
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
Cheers. Definitely going to have to on-device testing, and find a way to ensure it's not on the main core, probably by flogging the main core at the same time as the tests run.
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.
i'm waiting for the day when you will have a GDC talk on "how to C in C#"
You've got me pegged. Though it'll more likely be on BitStream, due to the profanity laced rants that make it me.
i think they are used to strong opinions
substack?
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.
many impostors though
wow. That's amazing. That folks would try to fake it in a space that can be quantified.
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
hey, sorry for bothering but i'm struggling to integrate commnd pattern in my code. i understand it but can't figure how to integrate it ... :/
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
}
how i made a key door sys, pls help
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?
You can with -nographics but that might prevent rendering with the camera.
It sounds like you want to disable Update, not the render pipeline
@slate stratus are you not able to just do an editor script?
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
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
would it re-render the scene without going into the next frame?
Re-render?
^
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
right now it produces an output like this from the standalone player
Is there anything wrong with that?
i can't, the asset bundles are customer-provided
So you do want particle effects?
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
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
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
Just do it in a loop
in start?
i'll try
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?
You can disable physics
I've never tried, did you?
I seriously doubt it
Since you want graphics
yeah i'll try something
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
yeah i'll try looking into it
i may just try disabling useless functions from a winapi level
Nah looks wrong
I doubt it could load generic asset bundles
I just read the short description
did you test with the safety and type checks enabled in the editor, or in a build?
I don't think Project Tiny even supports asset bundles
@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
You mean as a coroutine?
That'd just crash, you don't have a yield inside the while loop
well this code worked just fine now
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
}
why make this a coroutine at all? You can manually render the Camera (which you're doing)
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
Don't see why
It wouldn't crash
Why wouldn't it? If they have like....500 steps
Technically it'd hang but ๐คทโโ๏ธ
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
That looks fine to me.
No don't do that
If you do that you'll be rendering frames for 1s between
But if you use sleep you'll guarantee no code is run
It will block the main thread
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?
Which is what you want, right?
What timeout?
There is no timeout
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
lol, I think I'm confusing myself with old assumptions, I'll step out while you two solve this ๐
a player that sits in a loop waiting for new assetbundles to render from a server
There has never been a timeout.
You can have an infinitely long loop in unity
That's what the hang is
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
You mean "has stopped responding"?
Yeah
eventually windows may close the application
if it's unresponsiveto winapi's pings
But you're running this on CLI right?
Windows or Linux?
windows most likely
but if it constantly crashes on a long while loop then it defeats the purpose
i want it to be able to load and render the asset bundles~ in under a second and push the images up
the network throughput is 50gbps so the assetbundles will load quick enough
But I think that whole not responding thing is part of the window manager
yeah it is
not sure, only one way to test
this code didn't want to work https://hastebin.com/yitoforalo.csharp
one'd think there be more links on how to make a hung application not close on itself ๐
I just realized that if you do it this way in editor you won't be able to stop it
yeah i know
Honestly I think you should just do it the normal way and throw more money at your server
:/ can't offload the cost of that
Just disable the camera
then we can't render transparent images
Why?
The cost of processing will be so little compared the bandwidth
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
How slow is it?
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
Brutal. Have you profiled it?
not yet, how would i go about doing that?
Open the profiler and hit record
oh i see
You'll need to be doing it frame-by-frame to see
i just used the standalone player and used a stopwatch to time it
Where the costs lie
But that won't tell you what is using the time
and made this
If it's the rendering itself you're SOOL
the most heaviest call is loading the asset bundle for the first time and taking the first screenshot
Maybe first screenshot initializes stuff
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
https://github.com/karl-/pb_CSG
I'm trying to use this library in my project. I did everything as it says but i got The name 'CSG' does not exist in the current context error at that line :
var a = CSG.Subtract(... , ...);
A C# port of CSG.js by Evan W (http://evanw.github.io/csg.js/). - GitHub - karl-/pb_CSG: A C# port of CSG.js by Evan W (http://evanw.github.io/csg.js/).
https://github.com/karl-/pb_CSG/blob/master/CSG/CSG.cs
Looks like it's in the Parabox.CSG namespace
I imported it too
using Parabox.CSG;
on autocomplete it only shows Parabox.CSG.Demo
there's nothing else than it at Parabox.CSG
Check one of the closed issues in the repository.
You most likely need to add a reference to the assembly definition in one of your assembly definitions.
actually i don't know how to do that
If you don't use assembly definitions, deleting their assembly definition file might work too.
now it can't even find Parabox namespace
Then perhaps there are more than 1 assembly definition.๐ค
Hmm... Doesn't seem so. Try refreshing and reopening your ide.
There was one more i think, i deleted it and it works now. Thanks
Glad you got it working, it is a really nice package with a easy to understand and clean API. At least it was when I made my super advanced PR ๐
i've just found out it wasn't what i was looking for :D
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```
so just a series of enumerations
It's literally just an enum https://docs.python.org/3/library/enum.html#creating-an-enum
cheers
Any guidance on how to extract each frame in video and put it into a List<Texture2D> ?
Looks like you can set the frame of a VideoPlayer here: https://docs.unity3d.com/ScriptReference/Video.VideoPlayer-frame.html
Then you can copy the texture out from here: https://docs.unity3d.com/ScriptReference/Video.VideoPlayer-texture.html
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.
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
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.
https://answers.unity.com/questions/1308329/billboard-sprite-shader.html something like this?
Unity is the ultimate game development platform. Use Unity to build high-quality 3D and 2D games, deploy them across mobile, desktop, VR/AR, consoles or the Web, and connect with loyal and enthusiastic players and customers.
Ok thank you :)
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?
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 = ...)
Where did you get temp from and what type of object is it
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
I had this bug when using the default built in sprite material though this issue should only be present in the unity editor and should work normally in builds, if it doesnโt then I donโt know
I've just figured, it was trying to access reference to reference to accidentally removed by me prefabs...
Interesting! Will have to test that out. I just solved this issue by creating a Script that updates the size in LateUpdate and then disables itself.
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);
} ```
delegate is a keyword, not a type. It looks like OrderBy takes Func as its type argument. So take a Func as your argument into OrderList, probably?
you dont really have to pass in a delegate, you can write it right there and then
Yeah, I surrounded it by ?? its supposed to be pseudocode because I don't know how to initialize that delegate.
I'd expect it to look something like this.
public void OrderList(Func comparer)
{
myList.OrderBy(comparer);
}
this is a simplification. The class uses an OrderList method which will reorder the list based on various factors happening in the game. the getParam1() function isn't actually in the same class as the OrderList method. It could come from variuos objects
public void OrderList<TKey>(Func<myClass, TKey> func)
{
myList.OrderBy(func);
}
You should look up delegates, Func, Action, and lambda
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
Yeah, so you got it.
Func is an Action, but it has a return type.
thx guys, I'll see what I can find
^
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.
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.
392
(I have no opinions of my own, but this thread was interesting)
Oh thanks, I saw this but never got back to read the comments on it.
Can I define custom collider? I have custom raycasting algothithm
Using a mesh collider is the best you can do I think. All of the current colliders have a C++ counterpart.
nah, not an option. The "mesh" is driven on gpu
The problem is that Unity uses PhysX which only supports Box, Sphere, Capsule and Mesh colliders.
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.
I dont think I've ever seen a function in a function in C#, why would u do that?
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
Local functions are a mistake IMO. I never use them. Most often when I see them it's a beginner who doesn't know what they're doing and put the code in the wrong place by accident. A lot of people do like them though
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
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
Truthfully I am really split on them my self. They can be very useful, especially to be able to access other parameters in the main method without having to pass a a bunch of parameters. But I also almost feel like they are a code smell sort of? Idk
They let you make methods that are only used in a single method without cluttering the class, and they can access variables defined in the parent method that you would otherwise have to pass as parameters.
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.
The idea is that they prevent clutter when working on other parts of the class because you cannot access the method that has no use to you.
Huh, you learn something everyday I suppose
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.
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
Yup, just player prefs. So I should be good then?
yup!
I use them all lot. They capture the outer scope which is very handy.
They can replace lambdas that need to capture a variable. e.g. inside a loop to be then queued as a job or event handler. this makes that code more readable than methods with extra arguments 2 pages down (for me at least)
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.
does anyone know if its possible to use unity's orange outline in editor to outline other stuff for editor tools?
100% agree. There's very few benefits and many traps.
Isn't this a case of just adding an inner scope for aesthetic reasons? You're already in the outerscope, why do you need an inner scope that's not got a name and only used once?
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.
Among other things local functions provide graceful way of escaping nested loops avoiding goto usage.
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).
Oh, if you're only using it once it's not useful.
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));
}
I think you might underestimate the value of closures if that's the case. People don't use delegates because they're "cool". They use them because they're a useful abstraction.
We were talking about local functions though which do not allocate on the heap unless converted into a delegate (via passing as an argument). They still have access to the outer scope which behaves like a closure.
excellent explanation. THANK YOU!!!
Cheers. This incredibly succinct response is highly helpful. THANK YOU!!!
This is next level guidance and insight. And wisdom. I say from ignorance, but will digest and attempt to apply to something mechanically similar, in that I have something that diverges only on input values that I'm currently messing with, and this might solve exactly the same code duplication. I cannot possibly thank you enough for this amazing share. CHEERS!!!
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.
Yes, I'm merely (poorly) pointing out the overloads of => are... well, if I was running C#'s design, I wouldn't have overloaded this thing so heavily, and would have found a few things uniquely different for those operations that are local, inline and not creating garbage.
You're welcome!
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)
I don't know Java, and barely know C#. I use it like it's C plus a lot of work to avoid C#
Well, C has function pointers and C++ has delegates
I've never understood delegates as references, this, to me, seems like a lot of work that shouldn't be done when pointers to functions are somewhat available, via being a bit unsafe.
"pointers to functions" are actually delegates and also cause heap allocation
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 ๐
i.e.
void X() {
}
void Start() {
someObject.SomeEvent += X; // X is wrapped to capture its `this` and causes an allocation.
}
if you use it like that, yes, it probably is exactly like a delegate. It even looks like it.
JacksonDunstan.com covers game programming
Ah yeah, burst compiler is its own beast. I don't know much about it.
i've watched this video, and i'm trying to think of a way to have procedural code in unity, when c# and unity are inherently object oriented
i think it'd need things like static helper classes to contain pure functions because you can't have standalone functions in c#
Yeah, pretty much. I've started to do it a tiny bit
but i also find that my game code doesn't actually have those big blocks of procedural code, so ๐คทโโ๏ธ
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
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
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
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
and this is also possible ad-hoc, without any extras like ECS
all the time, everywhere
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
it depends on your game, but for me a mixture has ended up working best
cool video tho thanks for sharing
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
yeah and i think game development isn't exactly like other software development
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
best practices for programming won't always apply
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
and you have much more/deeper interaction with non-tech people that are critical to success
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
I love this video
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
Or feel worse about it
(is it okay for me to abruptly ask a question right now?)
Not now! (joke)
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)
Did you try adding parenthesis?๐ค
public ref T Value() => ref _value;
Ah, wait. That's just a propery
Yeah, it compiles as get_Value when using a property.
I did try both, it doesn't work either way.
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.
ah gotcha
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.
Ah, that might make sense. For the generic the compiler needs to create a new definition of the class specialised to your templated argument. The compiler will not know how to do that?
Speculating a bit here.
Whereas the contents of the DLL will otherwise be precompiled bytecode.
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.
What unity version are you on?
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.
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 ๐
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:
- Remove the
refkeyword. - Remove the generic.
- Upgrade to a future Unity version that supports this.
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.
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
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.
Um... "uncompressed"?
(JSON)
Do you want a database or a game server as a service?
Just put it in the database
I've already got a game server console app.. so I suspect I just want a database? I don't know the answer to that Q, TBH. I'm not exactly sure what a GSaaS is..?
@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.
Should I denormalize the data and pull out what I need into other columns in the database? Or pretty much my tables are going to look like { Guid , JSONblob }
Cool. Didn't know that was a thing.
Yeah, you can totally do the latter.
If you just want a simple data store I'd just use a document store database
I cut my teeth in an era before JSON existed.
You can even index fields in JSON
read original question
If your data is relational and want a little more effort you should use postgresql e.g.
I did, I'm giving options
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.
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
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.
Well, you can also use an ORM that does the object -> columns for you.
It's not hard to transform a JSON object into columns -> value mapping.
You don't have to hand write every transformation.
Chances are that json columns are slower than a nosql database bt I haven't actually done the benchmarking
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"?
function handleInsert(json) {
const valid = pickKeys(json, permittedKeys);
db.table("my_fun_records").insert(valid);
}
(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)
And with GSaas, I meant things like Metaplay
I'm not sure what BI is, but it can render arbitrary queries.
And there's a bunch of other ones
So almost certainly yes
business intel
ie - figure out things like DAU/MAU, LTV, CPA (perhaps we have some integration with advertising spend or acquisition details)
Yeah. That's easy enough. You might need some more advantage SQL queries. But I used to write stuff like that for metabase all the time.
"show me how many players churned out after earning this achievement" or something that's... related to the game objects
"show me what percentage of my userbase has churned out after spending more than $1 in the store"
Yeah, sure. You can do that
select count(*) from users group by spend > 100
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
Although @flint sage's suggestion of an off-the-shelf game service is probably a good one.
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..?
Metabase has a visual query builder too which is quite easy to use, but I found it limited.
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
Are you asking for a web frontend to admin/edit a database that nontechnical user can use and that also generates a graphql or rest api
That could be a solution, yeah
I mean.. ideal is "bespoke admin tools" but I'd settle for "editable data with generated front end"
thanks, will check it out
Look at it, ask me anything about itโฆ have been using it a lot lately. Will tell you all the bad stuff
directus? or graphql
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
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?
call IgnoreLayerCollision again with the third parameter = false
omds thank you so much, didnt know there was an overloaded method
as always, check the docs.. with all due respect that took 3 seconds to google. ๐ https://docs.unity3d.com/ScriptReference/Physics2D.IgnoreLayerCollision.html
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
there's only one version
You probably looked at this https://docs.unity3d.com/ScriptReference/Physics2D.GetIgnoreLayerCollision.html
well regardless thanks
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.
www.paste.org - allows users to paste snippets of text, usually samples of source code, for public viewing. A place where lack of code gets binned; sharing code iterations since 2006.
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!
You're declaring and initializing the list inside Start(). After Start() finishes, the list is discarded because it goes out of scope.
(this is a #๐ปโcode-beginner question) - google some terms like "scope of variables c#" and "class members"
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!
you duh best โค๏ธ
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)
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.
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
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
No worries.. And just FYI these questions should probably be in beginner-code.. or.. ๐ the mods might get cranky. ๐
It'll be fine, now I know.
so I won't mess up next time :>
(if no one answers just wait a while and reply to yourself and ask again.. politely) ๐
like this
Got it :>
-
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,foreachsyntax,System.Math.Maxor use Unity's math library. -
You probably shouldn't crosspost if you don't get an answer in 3 minutes.
Sharpings job is to say "It's a beginnercode question"
hah
just saving the mods the work, right? ๐
I won't make the mistake again ๐
thx
you don't understand how much time this one line saved me.
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?
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
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)
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
(and lol, I misspelled "Behavior")
I'm gonna use my brain hard
๐
System.Collections.Generic.Dictionary and data structures (in general) should be high on your todo list
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
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:
- SetActive(true)
- Start the coroutine
- 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.
@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
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)
this seems to be overengineered and
i dont understand the more control over it all , what control do you lack in DOTween?
probably could have used DOTween, but I wrote this before I knew about that and .. it's worked for me shrug ๐
I like the approach of building it yourself to learn versus using some off the shelf tool.
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.
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);
Personally, I could never figure out the syntax of DOTween, nor how to get it to stop spewing garbage.
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.
those arent objective reasons
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?
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.
You're making a theoretical problem up in your head (that this leaks into big projects) to then use a trope/mantra (NIH) for something that is absolutely crucial to using Unity (understanding time and movement), and not done well by ANY of the existing libraries.
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?
The best library for time, far and away, is MEC (more effective coroutines), but it's still got the coroutine problem.
In a fast moving Unity space, relying on third parties and their updates leads to many, many more problems!
Its not a theoretical problem. It practical and present in a lot of projects.
What is the coroutine problem?
to the person you're replying, for me, and everyone else that's needed an elegant tweening solution, our use of our own tweening libraries has solved many more problems than it's created, and we're likely not in big teams, and it's not likely the habit you suppose it to be... both of which (the big teams and the habit) are theoretical problems.
Can you show an example? Generally anything that is a struct is passed by value unless boxed (cast to object)
You said you couldnt figure out the syntax and allocations, so i take it with a grain of salt that dotween couldnt handle your use cases
the states the I made aren't structs but just plain old classes. If I declare a variable via heap inside State A, and pass it to State B.. well I guess the answer would be passing it as reference right?
You are misusing the terms.
Ok maybe not, you need to show an example
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.
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
just working with what you said