#archived-code-advanced
1 messages ยท Page 119 of 1
Reproduction steps: 1. Open the attached "repro_IN-36000SlowBuild.zip" project 2. Open File -> Build Settings 3. Select "WebGL" a...
"won't fix" ...
sounds like they arent sure if its a regression of an old bug or not ๐ค
Hi all, I am working on a project where I am generating procedural terrain and storing said terrain data in cells (think along the lines of Minecraft's generation), Right now I am creating these cells and storing the data in chunk objects (class objects). Since i am now trying to optimise this I want to move to structs so I can utilise native arrays.
My main goal with this though is to avoid unnecisary recreation of structs, such that I need to modify a single value during the generation phase of these chunks I would then need to overwrite the original copy with the new version with updated values.
I have been looking in to access these with pointers and unsafe code, below UnsafeUtility seems to allow me to get a reference to the original version from within the nativeArray:
ref CellColumnData cellColumnData = ref UnsafeUtility.ArrayElementAsRef<CellColumnData>(chunkColumn.cellColumnDataArray.GetUnsafePtr(), columnIndex);
I would like to be able to do something simular with NativeHashMaps, as I am storing the chunk data right now in a Dictionary<int3, Chunk>. Converting the Chunk to a struct would be fine but I can't seem to find anything that isn't AI generated rubbish on actually being able to access the original copy of these structs as references.
What is the "correct" way of actually doing this? I was considering directly assigning memory using Marshal, but reading online that Burst doesn't apparently work with memory like that?
Any help with this would be appreciated.
You can get a ref to a struct in an normal array without unsafe (i think?)
but what is Dictionary<int3>, is that the 3d pos for the chunk?
Yeah, unity mathematics has int3's, basically vector3Ints that are meant to be lightweight.
dw im aware of the mathmatics lib and burst
This can only be discussed by looking at the specific code or by discussing fundamentals of data oriented optimization
From what I remeber accessing structs using ref in a NativeArray give an error for "indexer value returns tempory value cannot use ref"
it is very likely that without doing everything exactly right, you wonโt gain anything
ah crud yea i mean a real array[]
Yeah thats the crux of the problem, I am trying to get the code sorted to then work with Burst in ParralellJobs. So I need native arrays Dx
You fist need to understand how jobs/burst improve performance
cause there is a lot of overhead involved when using both and you need to understand how to get a net positive result
Mainly I am trying to use it for parallelisation, I am currently processing a large amount of data on cell by cell basis, I have already optimised things like exit early cases for situations where cells are invisible but since its all done in sequence its still slow.
well, without specifics not much can be said
I have already transitioned a chunk of the code to using jobs, and have got significant perfornamce increases. its just specific regions that need to be fixed now (optimisation pass, and setting up rendering groups). However as I said since all the data is being stored in classes, it can't easily move this data to execute on a job without a significant copy paste job from the class to native arrays.
Ideally I would have a single true copy of the data that is read only sent to the jobs, but can be accessed and modified outside of them.
I guess, if specfics are confusing things, my question boils down to. How would I store structs in a dictionary like way, so that I can both access them by reference and use them with the Job system without needing to copy data.
I dont think this is possible because the dictionary could move the contents at any time (thus making a struct ref invalid)
Assuming you have the class versions stored in array somewhere.. can you access that in the jobs system? If so, you could just pass an int as your "struct" to reference which class to use in that array.
The job system to my knowledge does not like managed types.
(never used Job's so shot in the dark) oh well ๐ฆ
Am I even correct in thinking that the job system doesn't like pointers to structs? I read this earlier when I was thinking of instead parcing a NativeHashSet of NativeHashSet<int3, Chunk*> where chunk is created using Marshal's malloc?
As that would mean the original copy is kept untouched, but dupicating / copying the pointer doesn't really matter at that point.
is the issue that your classes ->srtucts are large, and have lots of members (bytes)?
if so, perhaps you could convert one class to multiple structs- so when you need to change something, only a small amount of data needs to be copied around?
Not to large, but not small either. A single Chunk / ChunkColumn stores tempuary data for world generation (needed by neighbour chunks too), the chunk column holds smaller structs for each cell column across x, z. Which the Chunk holds an enum on each cell, which is (4096) cells in total per chunk.
So even though their isn't a huge amount of data in these things, if I can avoid unnecisary copying that would be ideal. especialy if I am just updating a boolean or such.
Well to put data into and out of a burst job it will always be copied
For the jobs thats fine, I more mean in the general use case of the program
Jobs wise, i am treating all data as read only
So was the problem not copying in the job when accessing this shared int3 -> Chunk map?
No no, the problem is that I want to store my chunk data in a nativeHashMap, so that I can pass it into the job system,
However, I also want to access and modify the values in my normal c# code, (like populating cells and checking for visibility in the optimisation pass). So I would like to modify the original reference to the structs while still having them in a format that can be passed to the job system
"Which the Chunk holds an enum on each cell, which is (4096) cells in total per chunk.." could you store an array that is 4096 times larger and use something like (chuckIndex *4096 + cellIndex) to access that enum?
Well to be supported the map value has to be an actual struct or other supported type
that would only work unfortantly with linear chunk indexes. Since I am using 3D chunk coordinates I would not know the position of the given index.
ah.. so could you store those when you build your array (in a second array)? [chunkOffsetArray[chunkIndex] + cellIndex]
im a tad confused following this tbh. Is a chunk 2d?
I'm not sure what you mean.
When i can i always do a single dimension array for 2d grids of a known size (and ofc can be extended to 3d)
Chunk is 3D, its a 16 * 16 * 16 object that holds data for 4096 cells, which spans an infinate grid.
This is why it needs to be stored in a hashmap / dictionary as their is no upper cap
And are chunks placed in 3d or 2d?
What do you mean?
Is it like minecraft where chunks exist in a 2D grid is my main question basically
I don't see why that matters for this issue, can you explain why you ask? @echo coral
Game logic is 3D, but yeah mainly the question is about storing the data in a way that can access the structs by reference in a burst supported format
From what i understood they want to be able to access many chunks by ref but ofc using a map/dictionary prevents this
But if you could also group many chunks into a fixed sized collection you can work on the bigger group by references.
(Ignore the terrible visuals, this is just basic rendering atm)
It seems strange to me that their isn't just a way to access the raw pointer to the structs memory while its in a native hash map
Usually its because of relocation
Wouldn't the pointer also be relocated though?
managed class references do this but in native code its not a thing
If you have a pointer to memory there is no guarantee after that what it points to still exists.
Even if its generated using UnsafeUtility.Malloc or Marshal?
That will because you are managing the memory
If you malloc then ofc it will be safe to use until you free it
But malloc isn't burst compatible?
Hmm, actually
"Persistent allocations should work within Burst"
So much conflicting info xD
I may just give this a try then, generate the structs using Unsafe's malloc and then pass in the NativeHashMap as a mapping of int3's to pointers. If it doesn't work I may come back xD
this in theory works but ofc depending on where the Chunks are now allocated you loose the benefit of contiguous allocation
contiguous allocations? Like fast lookups as they would sit next to each other in memory?
sometimes, you can get a bump from the way the hardware works when you do that.
I think he means accessing the structs pointed to by the nativehashmap which aren't physically next to each other anymore
Actually, if you limit the amount of chunks to a square region around the viewer, you can use a perfect hash system and store the chunks in-place.
public static int HashCoord(int2 CCoord){
//perform a true mathematical modulous with the chunk coord
int2 hashCoord = ((CCoord % numChunksAxis) + numChunksAxis) % numChunksAxis;
//Linearly encode the remainder
int hash = hashCoord.x * numChunksAxis + hashCoord.y;
return hash;
}
This hash function can produce a perfectly unique index within the hashmap as long as two chunks are greater than numChunksAxis apart
Yea as that will give a speed improvement if there would be lots of memory access to elements close to each other
This is the system I use btw except in 3D--you can just rewrite any data at those locations because they cannot both exist with that limitation
I may look into this as I will want to know neighbouring chunk data for chunks.
Thank you all btw!
Yea having a larger fixed size block of many chunks will make it easier to handle. Hope you get something working as you want
Hello! I've started using the ui toolkit and the localization package together and I'm wondering about the update logic when binding LocalizedString.
As an example, if I bind a Label element through the UI builder to a simple field in a data source class. As such:
public LocalizedString Text;```
I've observed that setting the `LocalizeString` itself and setting the `LocalizationSettings.SelectedLocale` both trigger the binding. Now, i'm not sure if the binding mode `OnSourceChanged` is working just as intended or if the binding is checked every frame and that's why both of these scenarios work.
I've looked around on how I could debug this but I don't seem to have found any way to hook onto a binding trigger.
hey, does someone know what happened to Unity Runtime Scene Serialization and is it still available?
this is from code general, got recommendation to post this here cuz it is a little bit advanced so here it is
hello, i have been following a tutorial on procedural planets which i almost completed, and i have been trying to add a level of detail system (LOD) but im having issues with chunk generation, the verts and triangles are getting distorted when the chunks are generated and dont know why i get this problem, have been working on it for hours and im really starting to get frustrated, here is the code: https://scriptbin.xyz/kobupojini.cs
Use Scriptbin to share your code with others quickly and easily.
!code
๐ Large Code Blocks
Use links to services like:
https://paste.mod.gg/, https://hastebin.skyra.pw/, https://paste.ofcode.org/, https://paste.myst.rs/, https://scriptbin.xyz/
๐ Inline Code
Surround code with three backquotes. Not quotation marks.
To format as C#, add cs to the first line:
```cs
// Your code here
```
Add a comment with a line number if there is an error message.
ty, didnt know that
So if you've been 'working on this for hours' why is there absolutely no evidence of debugging in your code?
cuz i deleted the debug logs
so how do you expect us to help you?
also i have been isolating variables but not a lot progress
i cant find why i get the error, if its either something to do with normals or vertices and triangles data
we cannot run your code so it's up to you to provide data we can work with
which means Debug.Logs and Console screenshots
ok, i will give you that
here are 3 screenshots, by the way, in the code, the ConstructTree method is what generates the chunks(LOD), and the ConstructMesh method makes the planet with all its features, inside ConstructTree i have a variable that calls CalculateVerticesAndTrianglesOfChunk method, which is called until the chunk data with its triangles and vertices is calculated which means the level of detail of the planet.
i know the problem is somewhere between the code in ConstructTree method, because that is where LOD is calculated, there i specify a parentChunk that generates the children, there are 2 lists, which are vertices and triangles, they first get the data of the mesh that has been made with ConstructMesh, then after the calculations of the LOD have been done, i store that data inside those variables and convert them to arrays and recalculate the normals as the final part, and as you can see in the screenshot, i get those distortions, and i dont know what part of the calculation or data management is bad here
Does anyone know how I could go about achieving sharp shadows like this but with the Render Graph? I was trying to create a pass that overrides the main shadow texture but it hasn't yielded any results.
https://www.reddit.com/r/Unity3D/comments/1ctncax/i_recently_got_really_into_shadergraph_today_i/
I've been able to achieve the result I want by editing the Lighting.hlsl file in Packages/Universal RP/ShaderLibrary/ but I'd prefer to turn it into a Render Feature so that it's better integrated. I made this graphic to illustrate my currently janky process.
Hi, I've been trying to convert my json to the RectTransform, and I got it for the most part.
However, there is a huge issue.
If I combine 2 anchor types(e.g. X uses position+size whilst Y uses stretching) it breaks.
This is the function that's supposed to handle the data loaded from json.
What might seem odd at first is repeated if checks for the offset types.
This is intentional and I've done it because I use this to set the regular position, and from my understanding, it also overrides offset values, not just relative ones.
At first, I thought this was the issue, and therefore, I made the change I just mentioned above, however, it still doesn't work.
What happens now is if one of the axes uses the offset(different anchors), it overrides the relative(same anchors) position of the other axis.
I am honestly out of ideas and don't know what to do, any help is appreciated.
Thanks in advance and please @ me when replying, I am off to sleep now so odds are I won't see the message otherwise.
Is there any kind of event or method called tied to switching the display in GameView?
For some reason my game crashes when I change display twice. Like from 1 to 2, no problem, from 2 to 1 crash
I have a custom GPU rendering system that Im working on that I think could be the cause, so I want to ensure I handle those switch display cases accordingly, but I have no clue what's being called that could cause the crash
It seems that im calling Graphics.RenderMeshIndirect but they are not actually used until the camera is in the gameView. Aka, they are being scheduled but not called. So when I switch display, all the draw calls I called are suddenly drawn which crashes my unity
nvm I fixed it, I still have no clue how tho, was just trying random things
... why aren't you using JsonUtility? Like it looks like you're trying to ascertain all the underlying variables to a rect transform to get to/from JSON.. but unity provides an extension class for exactly this purpose.. you just JsonUtility.ToJson() or whatever and you're done
yeah, ToJson() and FromJson()
all of that stuff is well and good, but it might not be everything you'll need to recreate a recttransform
Components can't be properly serialized with JsonUtility
Or does it save some meaningful data?
components can't? it says specifically in the docs that any MB can
At least you can't deserialize them with FromJson
Oh okay yeah:
However, when deserializing JSON into subclasses of MonoBehaviour or ScriptableObject, you must use the FromJsonOverwrite method.
TIL!
because JsonUtility is awful and I ran into countless issues with it, several people on this server recommended newtonsoft and I can't thank them enough tbh
i mean, that's true too ๐
i haven't tried to actually serialize a RT using unity's method - but depending on what you're trying to do, i'd probably create my own POCO for "location" on the screen, and the just instantiate a prefab with the values i care about put into it.. instead of trying to make a one size fits all RT serializer
fun fact, unity have a package for newtonsoft json https://docs.unity3d.com/Packages/com.unity.nuget.newtonsoft-json@3.2/manual/index.html
there's a lot of stuff in RT under the hood, and i don't know what all of it is (I don't think I'm necessarily supposed to)
yeah, my brain died trying to understand it, I am not trying to serealize it tho, only deserialize it(which I managed to do in the end)
either rt structure and code are weird or I am seriously lacking braincells(prob the second one)
is there someone with knowledge in vertex manipulation that can tell me why the vertices aren't where they should be even though they are in the inspector
I'll show screenshots of whatever you may need to see
it seems to be stretched from the getgo, this is where the first vertices should be but they're clearly not
"aren't where they should be" isn't very descriptive, but from the naming of your vars there's a problem there already because mesh vertices are defined in local space. Are your GOs holding these all at (0,0,0) with identity scale and rotation?
the parent object is at 0,0,0 with identity scale and rotation, so is the prefab. The object itself is not at that location, but it does have identity scale and rotation and the position of said object is in the middle between the two points of where the vertices should be manipulated to.
How do I define the vertices in global space?
You can't. Vertices are always in object space. You can convert world space to local though. It's gonna work as long as your object doesn't move, rotate or gets scaled.
It does not after creation, so that'd be fine by me
that fixed it, thanks!
Hey guys, has anyone ever implemented the transvoxel algorithm before? I'm trying to do it on a shader but I've noticed that the LUT's given by the github linked on https://transvoxel.org/ doesn't match the obvious way of finding the LUT's index. There's this following diagram in the paper, figure 4.16.
6---------7---------8
| | |
| | |
| | |
3---------4---------5
| | |
| | |
| | |
0---------1---------2
So if for example nodes 0, 1, 2, 3, 4, 5 are underground and 6, 7, 8, are not, The LUT index should be, 0x3F or 63 whereby the first 5 bits are set. However when I look at the "transitionVertexData" table on https://github.com/EricLengyel/Transvoxel/blob/main/Transvoxel.cpp, I find that the 63rd entry has vertices that don't reflect the isosurface at all. My best guess is that the look-up index isn't determined with the same diagram, but I can't seem to find any reference to how it's found anywhere.
Just looking to see if anyone's done it off these LUTs and knows what's going on here
I found the issue, apparently Eric Lengyel when writing the LUT made the corner order follow an archimedes spiral when finding the look-up index.
6---------5---------4
| | |
| | |
| | |
7---------8---------3
| | |
| | |
| | |
0---------1---------2
This is in spite of the corner index the LUT references being in a different order. He just never noted that down anywhere, causing me a few days of agony. Hopefully he amends this or someone puts a post about that.
Honestly there's no reason I can think of of why the index is formulated following an archimedes spiral. Low-key I think he just did this to mess me up
huh, yeah, it's not like this is a massive dataset that needs a clever traversal order
that technique looks neat!
Maybe it helps with expanding/contracting the indices to a 2 by 2 grid by dividing/multiplying by 2
Hello, I'm trying to make a Native Plugin for a feature that is only available in C++ but I'm having issues with .h files not being packaged with the .dll. How can I solve this issue?
how are you building the dll? what do you mean specifically about the header files, is there a compile error?
I was able to solve it, the .cpp and .h source files were being included in the unity build process
regardless @echo coral thanks for coming to my aid
ah right yea that usually works reliably when you put the src files in project ๐
Hi ๐ I'm programming a sim/tycoon game where procedural stuff is being generated by the player. Let's say the player builds walls.
I keep an underlying data structure of wall placement which gets updated anytime there is addition or removal. I'm wondering how to properly decouple logic from my data structure and MonoBehaviour.
I either need to update the Mono class (mesh, collider, etc) from my data structure or the other way (update data structure from Mono class).
What's the advised way of representing this 2-way relationship?
- Centralization with a dictionary? Like assigning a same id to both the instance data-side speaking and in Mono class
- Class fields? But I wouldn't like having a direct ref to my game object inside my data structure
- Other Unity pattern shenanigan that I may be unaware of?...
It kinda depends on the needs. Do you want the DataStructure to be unaware of the monobehaviour ?
Depends on what you call awareness ๐ I need both the Mono class and its underlying data structure to be accessible
Currently I'd have a WallBehaviour (Mono component) and Wall (which is from my data structure)
Why do you want to seperate them ?
I feel like a separation of concerns would be relevant, as MonoBehaviour exposes stuff to the engine (mesh, physics, etc). 'Wall' class is a plain-old struct. I'd like to see my 'WallNetwork' interacts with Mono classes as little as possible.
And why does the wall as a reference to the monobehaviour ?
If the idea is that the Wall could exists without a WallMonobehaviour, you can either use events or nullcheck before accessing the monobehaviour.
If you truly wants to increase the complexity simply to be cleaner (for no beneficit), you can use an interface to obfuscate the relation between wall and its monobehaviour.
It's not much about ownership because each 'WallBehaviour' will be associated with a 'Wall' whatsoever. It's more about considering traversals, algorithms on the data. I don't feel like using MonoBehaviour classes for that is a good bet
but I may be wrong and overengineered it, of course it would decouple logic, but it will give more sense to it
I also try to decouple data from Mono if I ever need to feed data to a job, later on
if wall is a class then why not have the monobehaviour reference that and not hold data itself? If its a struct then as suggested, use events and some manager to sync updates
Yup thatโs already the case, except that Mono-related stuff is keptโฆ in Mono class ;)
My concern was more about cleanly keeping track of Mono from data, and reverse
There is often nothing to gain from having a non-mono representation of a world object. Usually it only makes sense when the structure of the backing data is significantly different or memory has been exhausted. Performance benefits are not usually unlocked by having a poco dual. You also often find that the lifecycle that mono gives you will have to be recreated in the poco and sync between both is a frequent source of bugs.
if you want to have a clean/efficient representation, use entities, donโt reinvent game objects just because you canโt โnewโ monobehaviours.
Currently I am creating some kind of space/universe thing based on a serialized nested list (probably later json or whatever coming from api). I keep that serialised classes as data objects and assign them to the runtime monos to let them do whatever they need to do visually
In fact, if your object live longer then your Monobehaviour than it is useful to have a dual representation. Otherwise, as you stated is usually more of headache.
It would be "better" and "cleaner" to have a dual representation, however it is mostly a lost of time and effort to make because it is unnecessary in 95% of time.
Yeah I've seriously considered switching to entities
You need to ask yourself why are you doing it. Doing something simply for it to be aligned with best practice is usually an error. Mostly because those practices are not created with Game Development in mind.
Yeah yeah sure, well I guess I'll go with MonoBehaviour on that
Embrace the tool you use, do not fight it. ๐
Reading through discussions on forums it sounded like MonoBehaviour is the root of all evil lol
A project surely benefits from limiting them as much as possible though, I prefer to use them only where ultimately necessary ๐
(Primarily concerning lifecycle functions)
MonoBehaviour is tied to visuals in my head. I try to do everything in there, that is not processing data but rather position stuff and so on and needs to rely on the unity execution order. Data driven objects are just classes and only singleton managers and staff alike will inherit from monobehaviour to be accessible in the editor and observe data fetched.
#archived-code-general message
heya, does anyone here have a brain for camera matrix math that could help me out? I'm almost positive the issue here is with having my camera tilted down at a 30* X rotation, but I am absolutely lost as far as how I can fix that
crossposting wont speed this up
apologies, I wasn't sure if camera matrices were a shader thing or not
but you posted a coding channel link ๐ So you did post it on two coding channels and not even #archived-shaders ๐ OR? ๐คฃ
I originally posted the problem there, but someone answered my original question about why it was happening and I realized it's a camera matrix issue
so I posted the link to reference the original question with my added info from the answer
since I figured camera matrices were less of a general thing
Okay, just hard to follow that over 3 channels ๐
np, that's why I included the message link to the original question
So you say, z axis is your problem?
I think many share this association but it is far too limiting. Rendering is really just a small part of all the common problems that a game object solves. Many of those are only evident late in projects of an appropriate scope and when the team hasnโt gone off-roading and lost in the poco woods. That said there are endless opportunities to build systems adjacent to game objects that do not need or benefit from MonoBehaviour. Itโs just that usually, going โall inโ is trouble.
Keep in mind the scope of being a fast pacing chat and the range of people knowledge here. I agree to your statement, it was more likely a very rough distinguish to start from and then keep adding details to that categorisation
No idea what you are saying.
no worries
The sharper the angle the camera has, the less it needs to move to move by one pixel. Think about the limiting case -- at a 90 degree angle, the camera moves...an infinite number of pixels when it moves around
hmm, right, that makes sense. but there has to be some sort of equation to allow it to accommodate for that difference right? with the exception of 90* of course, though in that case it can't jitter since Z movement at a flat angle would be static in that case
I did find this but it didn't work in my case, and is a bit messy
Hey guys, basically, I have a vertex on a mesh, for that vertex I want to return a vector3 which would represent the up direction for that point on the mesh, how should I go about doing this?
In what context. What do you mean by you "have" a vertex?
Is this based on a raycast?
No I just have a mesh and on that mesh I need to get the up direction for a vertex
In general if you have a Mesh object in Unity you can get the surface normals in the .normals property on the Mesh
so if it's vertex v, then the "up direction" for that vertex is Vector3 normal = myMesh.normals[v];
ah that looks promising will look at that
Assuming by "up direction" you actually mean "normal"
Just note that every time you do myMesh.normals it copies the entire array, so you should do it very rarely and reuse the array if possible
found this on google thats effectively exactly what I want
Yup gonna try it with that thanks
I was never particularly good remembering math terms so I didnt know "normals" was the thing to look for but hearing it now makes some supressed math class memories come back
does anyone know what can be causing this
whenever im playing my main game scene in development mode im getting this
tried 3 unity version still its the same
unity 6000.0.33,29,20f1
can you decode the stack and then send it?
how to do that?
use android logcat and pray you kept your symbol files from this build
you essentially configure the path to the symbol files, open the stacktrace utility window and paste in the stack and decode it
is this it?
i configured symbol paths like this
if i put the symbols symbol path at top i get this
@echo coral
any idea?
huh the il2cpp one didnt work, did you copy that one too?
looks like some internal unity api though
it is il2cpp symbol
that is a null ref exception. looks like trying to access a destroyed gameobject
but why is this happening only in development mode
its working fine in release build
i was making development build to profile my game
there is some performance issue
and out of the blue it starting crashing when i go to this scene in development build
last time when memory profiler was working i went to that commit as well
but still its crashing
a null pointer deref is not the same
i even went back to the unity version i had used to profile at that time
its the same
crashing
there are 3 scene in my game - menuscene , practice scene , main game
menuscene loads fine
even practice scene
when i go to main game
it crashes
please type in full sentences you are not a 3 y/o
and this is happening only in development build
my bad
ideally id like to see the last 3 stack lines decoded
how to ?
i can make a build again if theres any steps to be followed
did you actually put files there? go check
i put a manual path cus we use a build slave for builds
build a dev build again to a custom path and after copy over all 3 .so files
copy 3.so files from ?
to a custom path?
wherever you configured
i only see 2 .sofiles
i dunno if it needs to be configured to make the il2cpp one. I presume this is arm64 and also using il2cpp for scripting?
can you show all of the ones that got decoded properly...
best you can do here is figure out if this is your code somehow breaking, unity code or some library
kinda yea. They the green we have is all from libunity so its some internal unity bug
next step is to search and hopefully find a pre existing bug report. else update to latest patch ver and try again. If still broken then report it yourself.
@echo coral thank you so much i solved it
i was calling garbage collector manually
i removed all of it
and now its working
thanks for pointing in right direction
i was hopeless
you never normally need to do that but it shouldn't crash your game ๐ค
glad its solved though! decoding crashes is the best first step to find out the cause!
i was calling garbage collector too many times maybe that was causing it
and it was crashing in low end devices
99% of the time you should not call it manually like ever
that is not how you fix a memory leak
your game was crashing crashing cause you were manually calling the gc then some other code was trying to access a reference that was deallocated
i did that gc call thing in my initial phase of optimization .I read it somewhere
anyway now i know it's a bad thing
Resources.UnloadUnusedAssets();
System.GC.Collect();```
i was calling these both
Resources.UnloadUnusedAsset should do the work right?
i will remove GC.collect from everywhere
UnloadUnusedAssets calls GC.Collect itself yeah
thank you
(Well, to be more specific, it doesn't call GC.Collect but internally it activates the GC so it does the same thing)
GC shouldn't ever delete objects still referenced so this is a bug
When you call it manually you are just making it happen sooner
Ofc if you used unsafe then this could happen perhaps but I presume not
If the Unity Object isn't referenced by a static or Scene then Resources.UnloadUnusedAssets will remove the object even though it could be referenced on the stack
(which is mentioned in the docs; it's a pretty easy thing to overlook when it's called interally via non-additive scene loading though)
The managed object for it should still exist but I would expect the engine to account for someone trying to use an asset that was destroyed safely
If you've set the optimisation level to not throw exceptions for null reference exceptions then it will crash
Can you change this for android? Doesn't seem smart to change anyhow
https://docs.unity3d.com/6000.0/Documentation/Manual/scripting-backends-il2cpp.html
Enabling runtime checks using Il2CppSetOption
In one of my projects in the past, a 3rd-party porter introduced a build config that set NREs to crash, took a while to figure out what was going on
I think there's a setting that disables it project-wide, not just with attributes. It was a long time ago though so I can't remember
Oof that must have sucked to debug.
I didn't know this was possible and I'm finding it hard to think why anyone would want to do this. Id just do it in cpp if perf was so important at that point ๐คทโโ๏ธ
the idea is you turn it on for final builds in which you've presumably fixed any null reference bugs, it affects every single object dereference so it's a free performance boost for your whole game
Classic example of who needs saftey checks if our code is perfect
There's not much point in implicit safety checks in release build anyway. It's not like you want the user to debug it.
its better to have an exception (that can be logged somewhere) instead of the game crashing. Id be hesitant to disable this except in a few specific places.
if you have spare CPU to throw at it, leave it on for sure then! that's not always the case though
When in debug mode, you can log, when not, you gotta fallback to something thats working for the user to know, whats going on
He does not know, an error occurred specific to your code, but know, something has to "try again" and revert to the last stable state to retry (unless your code is just wrong and will always return null ๐ )
when i say log i mean to some service where you can see it such as firebase or unity cloud
I discovered you can use a Tuple (vector3,vector3) as a dictionary key, presumably because it hashes it to make an id... but can I make it so that which ever order 2 values are passed in the key will be the same? AI suggests using magnitude to order them before passing as a key, I suppose if squared mag. might not be too big performance hit but still...
would have to be magnitude with axis adjustments though else 0,1,0 is same as 1,0,0 in order
hashcode for order I guess...
Are you asking if the key (a, b) and (b, a) will be same? No
Hash will be different, and even if you get same hash the equality is different
no I am asking how to make them the same - which requires ordering
Well then use any stable order
You can just order with X then if equals order with Y, so on
Yes so which for Vector3? GetHashCode?
well I am not sure what is for Vector3, this is the real question...
I just said
Hey, I have a little problem in project. It causes Unity to crash, and not like any kind of log crash where when unity crashes popups that beatiful window discribes if you want to send report to Unity and here are your logs if you wanna check what happend. It just crashes Unity completly, process stops to respond (Similary to the StackOverflow exception), but there is no any high processor usage in Task Manager. It happens randomly in different part of the game and in different actions taken. Do you have any idea how could I debug this mess?
that does sound like an infinite loop not exiting, can you try attaching the debugger while it's frozen and pausing it?
Visual Studio Debugger?
whatever debugger you use should work
Okay what shoud I look for?
if you press pause, see if it's inside a loop?
maybe there's a while loop with a condition that's always true
that would freeze in the way you described
up
But where I need to place break points?
Cause other wise i have bo fire Debug in VS and crashes Unity, but I dont see anything in VS
Okay
Okay
I catched it
Thanks guys
one of my biggest problems with the arkham games is that they were never 100% open world, like botw is. basically, the arkham games didn't let rooms be loaded in in the same "scene" as the main world, and i wanted to ask if anyone has any advice or resources that i can look into for making my game open world while still, yknow, not requiring 100% memory usage, lol.
i dont think that's a coding question
๐
although, its pretty simple from what i understand. just dont load anything that's far away.
see, what does that means exactly?
LOD should handle the rendering (not sure if that's automatic or not, i haven't used it in a while)
setactive false, or..????

there's a lot of different things that would be in the "open-world"
true...
so like, what does load actually mean?
get something ready to be used in the memory?
for most cases, probably just disable any scripts that aren't going to be near the player
a pretty common example is the super mario games. enemies aren't loaded until the player gets close enough to them. they're also unloaded once the player is far enough
LOD seems to work the way i should need it to work, so that feature of rendering is built in then โ๏ธ
i've never actually had to use it myself. i dont typically work with art assets much. someone else might have to answer that (or you can google it)
what about shaders?
also handled by LOD
wtf
its all built in ๐ญ
i aint even gotta do anything
well ill make sure but
thank you :)
well, you still have to define what LOD does to a shader. im pretty new to writing shaders myself. but, i think it's pretty simple
LODGroups turn different renderers on and off
Note that this has nothing to do with the LOD property that you can define for a shader
https://docs.unity3d.com/Manual/writing-shader-prioritize-lower-quality-shaders.html
This is an arbitrary number
You can use it to limit which shader is allowed to run at all
I've never done that
But, of course: if the low-detail objects use simpler shaders than the high-detail objects, then you will indeed get faster rendering
oh uh, never actually knew that. i just assumed it was the same thing, based on camera distance.
does any of you guys have information about Tower Defense games?
Wrong channel?
is there any good way to make something like [SerializeInEditor] or maybe [InspectInEditor]? (technically I could write a custom inspector, but it tends to be a pain to just vis a few variables, and annoying to make those variables act like the default behavior) I often find I want to be able to inspect the state of certain runtime values in the inspector and thus make certain fields at least temporarily public or [SerializeField], but don't really want the fields to be serialized outside of play mode and definitely want to avoid including them in a build. I was looking at the decompilation of [SerializeField] but it looks like its basically just a marker for some native code so it doesn't look like I can do something with that. I could technically #if UNITY_EDITOR but that gets messy and I then also have to be careful to put any code in an #if UNITY_EDITOR block rather than just getting defaults which occasionally doesn't get caught until a build so its also not ideal. Thoughts?
you could check out NaughtyAttributes? packages like that and Odin implement custom inspectors that will show fields or properties with certain attributes regardless of if they're serialized
if you don't want to add a whole package i believe NA is open source so you can see how it works
thanks! also, lol the odin store page videos doesn't work, the videos require third party cookies or something, and I'm leery about something with a non perpetual license but NA seems promising ... now to trying and get my team onboard
What you want is a custom editor
I use naughty attributes a lot its great (though can slow down the inspector if used a lot)
NaughtyAttributes creates a custom editor for all MonoBehaviours (and i presume for all ScriptableObjects), iirc
which does mean it can clash with more specific custom editors
@bleak citrus I could write a custom editor but its kinda a pain when I literally just want to inspect a few variables quickly, the point of my question was a simple way to do it for one off cases that is less horrible than just adding [SerializeField]
you can extend theirs to keep both but if you go the custom editor route you can draw the default and add extra stuff
I've definitely wanted this more than once
honestly even something like unreal's readonly would be nice to vis intermediate calculations and such that you don't want people trying to modify
Doesnโt inspector debug mode work for you?
oh god, don't remind me
private fields are still serialized
(which can actually footgun you)
Is Physics2DRaycaster bugged in unity 6? I'm getting no feedback on any 2D polygon collider events, no matter what I try.
Not that I've heard. What kind of feedback are you expecting to get?
Which collider events do you mean?
There are a few places out there on the web that all employ a similar type of solution to this. Dunno why Unity doesn't make it a standard engine feature. I use it all the time.
Oops I guess that's not exactly what you're asking for... but in any case, its a way to show the values in the Inspector without having them editable in the Inspector.
Yep NaughtyAttributes is the way to go.
OnPointerEnter, OnPointerClick, OnPointerMove, OnPointerLeave, OnPointerDown, OnPointerUp
Do you have an Event System in the scene?
Did you implement the interfaces? (did you add them to the class declaration line?)
This is programming advance, not programming beginner.
And as advanced programmers we check everything thoroughly
because we know we still make mistakes.
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.EventSystems;
public class Mask : MonoBehaviour, , IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerMoveHandler
{
[Header("Mask Settings")] public MaskType maskType;
[ShowIf("maskType", MaskType.Body)] public BodyMaskPart bodyMaskPart;
[ShowIf("maskType", MaskType.Head)] public HeadMaskPart headMaskPart;
[ShowIf("maskType", MaskType.Outfit)] public OutfitMaskPart outfitMaskPart;
[Header("References")] public MaskController2D maskController2D;
public void Subscribe(MaskController2D maskController)
{
maskController2D = maskController;
}
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("Click Detected");
if (GameControlManager.Instance.announceMaskHit && !GameControlManager.Instance.isInteractionDisabled)
//Announce and link to gameobject
Debug.Log("Mask hit: " + gameObject.name, gameObject);
}
public void OnPointerMove(PointerEventData eventData)
{
Debug.Log("Move Detected");
}
public void OnPointerEnter(PointerEventData eventData)
{
Debug.Log("Enter Detected");
}
public void OnPointerExit(PointerEventData eventData)
{
Debug.Log("Exit Detected");
}
public void OnPointerDown(PointerEventData eventData)
{
if (GameControlManager.Instance.announceMaskHit && !GameControlManager.Instance.isInteractionDisabled)
//Announce and link to gameobject
Debug.Log("Mask hit: " + gameObject.name, gameObject);
}
}
I know, I'm just having a laugh.
I see you have a layermask configured on the raycaster
do all the objects in question have the appropriate layers?
Aye.
I've spent about an hour going through every forum post I could find. Everything was already correctly setup.
it;s also possible a UI element is blocking things and eating the events
Try disabling everything except the object in question and the event system basically
and the camera
I tested with all UI elements disabled.
or in a clean scene
I also tested with everything but the cam, sprite layers I wanted to poke, and camera.
Absolutely nothing.
Another way you can debug this is with EventSystem.RaycastAll https://docs.unity3d.com/Packages/com.unity.ugui@1.0/api/UnityEngine.EventSystems.EventSystem.html#UnityEngine_EventSystems_EventSystem_RaycastAll_UnityEngine_EventSystems_PointerEventData_System_Collections_Generic_List_UnityEngine_EventSystems_RaycastResult__
see which objects, if any, the event system is seeing with its raycasters
Double check the INput Module settings as well
and that there aren't errors in the console, of course
(covering all the bases)
No errors, input has been working fine.
have you tested with more primitive colliders like a box collider or circle collider to rule out the issue being the collider?
Finished the timer script, had it turned off until I enabled it. Changed absolutely nothing else.
And it just starts working after recompiling. Despite not changing anything in that script, and putting it on a seperate one.

Thanks for the help guys, I think unity decided to have slow day today though ๐
Hi I have a lot of issues with a package using async Tasks. I need a Task to tell a Monobehaviour something is done (callback/Action), but it being a Task it can run off the main thread. I need to notify from the main thread - I mean all the tasks could just run on the main thread but what is the point of Tasks then instead of say coroutines? I find it an odd mix with Unity
Task continues on main thread =/= the task has to run on main thread.
yeah that is problem - can I run an action from a task but make it run on main thread?
it should only run off the main thread if execute it with Task.Run or something similar
ideally you would only use those kinds of Tasks if you actually want it to run off the main thread, like in a web request or long running background processing
if you want a substitue for coroutines you should look into UniTask
That's kind of odd of a situation, are you saying you have a task that's running on non main thread, and during its execution it needs to do something on main thread? So it needs to "do some work in current thread -> do some work in main thread -> do some more work in current thread"?
At that point I don't see why not just split it into 3.
If you are using UniTask, there are UniTask.SwitchToMainThread and UniTask.SwitchToThreadPool; if you are using Awaitable, there are Awaitable.MainThreadAsync and Awaitable.BackgroundThreadAsync.
It is not my code really but a package - no UniTask - which can end up off the main thread, not sure why or if it is meant to. I simply wanted to have an Action when things were complete. I do question this packages use of Tasks
If it's someone else's code, how do you end up needing to switch to main thread in the middle of it?
you can also create your own main thread dispatcher (or grab some implementations online) and route the stuff to the main thread
Is this firebase by any chance?
I second the recommendation to use UniTask for better async integration. You can await this Task (or use ContinueWith()) and then use Unitask to go back to the main thread.
You cant modify what happens inside their function unless you edit it.
No gltFast
Perhaps I can combine UniTask
Oh then im not sure what the problem really is
await DoThing();
await UniTask.SwitchToMainThread();
//use unity api safely
yeah thats nice
Is it possible to load a second scene, but keep the first one from not lagging? Anything I am trying doesn't seem to work ๐ฆ
I basically have a static scene, where the user can rotate around it with the camera.
A second scene, where a separate camera just makes pictures of the static environment. Every 5 second there is a different second static environment in the second scene. This scene is never in actual view of the user, just meant to save images somehwere in the distance.
All I can come up with is a second .exe, but it's not really desirable
Loading a scene is an expensive things to do. Without more information it is hard to know what could potentially work for you.
It's a bit hard to describe it ๐ค The scenes are not really intensive.
Hmm, imagine if you have a scene of a 3d model, static one. A fish let's say. The user can control the camera and rotate around it. Then there is a second scene which also just has a 3d model of a static giraffe for example in the far distance so the user doesn't see it. Where it just makes pictures from different angles. Every 5 seconds a new scene is added with a different animal. Basically I just need the user to not have the 1-2s lag spike when rotating the camera on the first scene.
public void LoadMainGameScene()
{
isLoadingVesselScene = true;
try
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync("VesselScene", LoadSceneMode.Additive);
StartCoroutine(LoadScreenShotSceneEvery5Seconds());
}
catch (Exception e)
{
throw;
}
}
private IEnumerator LoadScreenShotSceneEvery5Seconds()
{
while (true)
{
yield return new WaitForSeconds(5);
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync("ScreenShotScene", LoadSceneMode.Additive);
asyncLoad.allowSceneActivation = false;
while (asyncLoad.progress < 0.9f)
{
// This helps spread out the loading over multiple frames
yield return null;
}
asyncLoad.allowSceneActivation = true;
while (!asyncLoad.isDone)
yield return null;
SceneManager.UnloadSceneAsync("ScreenShotScene");
}
}```
!code
๐ Large Code Blocks
Use links to services like:
https://paste.mod.gg/, https://hastebin.skyra.pw/, https://paste.ofcode.org/, https://paste.myst.rs/, https://scriptbin.xyz/
๐ Inline Code
Surround code with three backquotes. Not quotation marks.
To format as C#, add cs to the first line:
```cs
// Your code here
```
Add a comment with a line number if there is an error message.
use a paste site for large blocks
Step 1 is to look at the profiler and see what exactly is causing the framerate drops
Maybe you're doing IO on the main thread for example? (Saving the screenshots)
This is also in Unity now - I missed the Awaitable section in docs: await Awaitable.MainThreadAsync();
oh nice, you can use that instead if you prefer. both do the same thing
does it have to be unloaded every time? it seems like it'd be smoother to preload it, disable the objects, then turn them back on when needed
you could try turning down the loading thread priority too but that won't help much if your performance problem is coming from the frame it gets activated
Yeah, it has to be. @sly grove was right though. Profiler did help me reduce it from 1-2s to 0.5-1s. I think the only solution is to load parts of it in chunks and only when there are periods of inactivity on the main one. I didn't know making screenschots was so cpu intensive
What is the difference between GraphicsBuffer and ComputeBuffer?
Your "scene" does not really seem to be heavy. I have done the exact same thing recently with "Hunting Trophy". Instead of loading a scene, I'm simply instancing a gameobject. Obviously, the resources (Mesh, Texture, etc.) are already loaded.
What I suggest you do, is if you do not need a complex 3D environment, but simply a prefab is to not use a scene. Finally, if yo do need a 3D scene, reduce as much as you can component and other scripts as it is mostly the Awake/Start function of each script that is costly. Also, I'm doing "screenshot" (Creating a texture with the information currently displayed) on the Switch, I do not think it the screenshot itself is CPU intensive, but saving it which can be done on an additional thread.
I use ScreenCapture.CaptureScreenshotIntoRenderTexture for the function.
GraphicsBuffer is a newer API to create buffers of all kinds on the GPU. ComputeBuffer is an older version, introduced when compute shaders were first implemented in Unity and only supports some buffer types, notably doesn't support vertex and index buffers.
There's no reason to use ComputeBuffer over GraphicsBuffer and I assume it will eventually be deprecated.
Has anyone ever been able to find a way to implement sharp shadows in the URP via the Render Graph API like so? I still haven't figured out how to do this.
Can jobs be scheduled asynchronously? I have a problem ahere I schedule so many jobs that the game stutters
Are you sure the cause is the scheduling of jobs rather than something else (eg creation/completion of jobs)?
A weird bug is happening when loading tile maps from JSON
It works most of the time but sometimes it decides to not work
I inspected the json nothing wrong there
I inspected the code execution order and its as it should be
but it for some reason loads onli one map and puts it on the wrong layer (so the contend for the background tile map loads on a different one)
But if I generate all the maps again and save them they load just fine and it works fine the entire day
but next day its broken again (am using newtonsoft json package)
if someone is willing to help me I'll send the code for more context
thanks in advance
It might be creation of jobs, but is there any way to cache that?
If you are not sure, always profile and understand what exactly the problem is, rather than throwing random solutions at the wall and praying.
That goes for any performance related questions.
Yeah of course, that's why I'm asking of theres any way to reduce job scheduling times, like asynchronously. I need to check again if job creation had any big impact since i don't remember, but the main thing was scheduling
hi, can anyone help me with my idea?
I want to render character's shadow, then move the character's bone, then render character, but I'm having problems and would like to get an advice
You haven't profiled it to know if that's the issue yet.
You are just guessing that's the issue and asking for solution assuming that must be the problem.
I have profiled and saw that scheduling was had the biggest impact, i just don't remember what was the second one. I did it this morning when i asked the question now I'm out of the computer until later.
But that's not the point at all tho, i appreciate the concern about doing it right, but I'm not asking that
I don't understand why you are jumping to those conclusions, seems a bit rude to underestimate someone like this
Should have shared the profiler data as well then.
It's not like we underestimate you, we just want to have the full context.
Otherwise it's just poking in the dark.
Because, jobs scheduling itself doesn't sound like something that would be heavy. Normally, it's not.
Wasn't trying to be rude but sure I could've worded it better, it's just that you have provided basically no context for people to help.
From my understanding as well, job scheduling shouldn't be a performance bottleneck either, so it's very likely to be many other things:
- Maybe your
new MyJob(...)is the part that's slow. - Maybe the reason
new MyJob(...)is slow is because you are creating/copying data every time instead of some kind of caching. - Maybe you have jobs that operate on an array of data and instead of scheduling a parallel job/one job that loops through the entire array, you are scheduling one job for each element.
- Maybe it's work done after job completion that's slow.
- Maybe ...
It's not realistic for people to help by listing out all the possible problems and solutions. Profiler data can help, code can help, but we have nothing.
Without context we cant do more than a google search could
Does anyone know what API is used if you want to have an icon in the editor down in the area where unity's icon/button for release/debug mode is?
Or if anyone has another idea for a good way to present a status display of an editor tool, I'd be interested.
This is a tool which runs in the background.
I'd like something visible if it has something to inform the user of without spamming them with popups.
google unity background tasks. Also #โ๏ธโeditor-extensions
Cheers
I see, well, i will get back then once im again in the PC so i can share screenshots and we can look into this more properly, thank you both!
what's the best way to implement states, buff and debuff like electrified state in a 2d game ? Ideas? Please...
Whatever is the dimension of the game has little impact...
You can just create a "Buff" or "Modifier" class
Thanks man
If you want more information, you will need to elaborate more. It might seem stupid what I just said, but there is many person that do create such classes resulting in cluttered codes.
they shimmer when moving
can you give some more details about what you want to achieve?
you can increase the resolution of shadows to make them "sharper"
screenshots are not cpu intensive. it really depends what you are doing and where the screenshot call is. what do you expect to happen? should the whole scene be rendered before your call to screenshot returns?
what do you want your behavior to be?
I mean something like this
this is only at 2k resolution but is crisp
I achieved it by rounding the shadow attenuation function in one of URP's shader function files, but I wanted to know if I could do this in the Render Graph instead
hmm okay but it doesn't look very good
i mean it's a wavy line
eh, I like it
also looks better at lower shadow resolution
compared to it being blobby
but yeah, I just wanted to use the Render Graph to do this rather than manually edititng the package file since it would be a bit cleaner imo
but I haven't been able to figure out if I can do that
why isnt this a feature in urp normally ๐ค
which feature? the shadow looks like a wavy line
shadows are kind of complicated
do you have soft shadows turned on?
if you have it disabled in the urp settings it doesnt work but wont tell you (or may be built in i forget)
Render graph just allows you to manage passes and stuff, it doesn't replace writing shaders or shader graph, so I'm not sure what you mean by that.
ah, darn
ty for the clarification
also @echo coral you can use this method Iโve been using if you want, even if itโs not super streamlined
It results in a stylistic shadow, which the standard shaders don't aim for I guess. They aim for PBR look.
it effectively just applies a threshold to the shadow attenuation
via rounding
I do wonder though, is there a way to disable bilinear filtering for shadows? because even with soft shadows off thereโs still some slight โsoftnessโ
and it could be nice to have pixelated shadows
Is there? Never noticed๐ค
you only really notice it at lower shadow resolutions
but it would be nice if you could toggle it for retro-esk graphics
Heya, I had a code architecture question. People always talk about seperating your logic from your visuals. I usually do this by using the Observer pattern (to trigger animations for example). The problem I'm running into is animations. For example, in our turn based game, unit A might attack unit B. In my logic, this is executed immediately. I'd have a listener on the health to update the health bar.
But what if I only want the health bar to update after the animation is done? Or what if I want to stop the player from doing actions during the animation?
I know one could use animation events, and have the animation event lock player input, but then my logic and animations are tied together.
How do you guys deal with this in your projects?
Is it even possible to make a screenshot Script that doesen't cause a 2 seconds long lag?
(Trying IEnumerator and IJob-structs, did not solved it either)
Hello, I had a curious thought. If we use Scriptable objects for lets say "health" . For a single player game, can a user modify health Scriptable Object in runtime and become "god' ? I am thinking in terms of fraud detection.
you should usually assume players can modify anything about their own game state they like, no matter where you store it
hello, i am also making turn based game . I am always filled with such questions and dilemma. lol . do ping me if you have any questions in code architecture, i would love to ponder over it. thanks
Yes?
It would help if you shared your current approach
so, I'm currently also working on a turn based game ๐
what I currently have is something like an animation manager, it listens to all of the gameplay events (who attacked who, who got damaged, etc), enqueues them and then play the animations accordingly
I'm trying to make them all cancellable, so at any point the player can trigger a new action and then the game should resume from the most recent logic state
There are several things you address here. Taking the example of the healthbar, you could just use callbacks to run an animation and at the end of it, call your healthbar method or rather call your data to update the health and then the healthbar is tied to that data update and updates itself.
An important thing to remember. Scriptable Objects do not save between runtime calls if you do not serialize them to a file and set the updated values on start of your app. If you just use SOs like in editor, they will get reverted to the exported state in runtime everytime you restart your game
Unity games are really easy both to mod and make custom clients for, like worst case scenario they can always change memory addresses, so to counter that you gotta get a bit crafty
Hm, but aren't you linking the animation back to the logic in this case?
You're calling an attack, which then has to wait on the animation, which only then updates the data right?
Somehow you have to know, how long you want to wait. You either can ask for the playing state of the animation or get the length of the animation and then wait for that amount instead of relying realtime on it. But that highly depends on your setup.
Of course you could also just let the attacker send an event and the receiver send an event and rely on that, but overcomplicating things can lead to unnecessary systems too. If you rely on visuals because something is animating dynamically, you have to link it somehow. First of all, what brought you to the "do not link visuals to logic" conclusion? Maybe its a misinterpretation thats confusing you? Just trying to get on the same page here ๐
To clarify, I do link visuals to logic lots of times, I'm mainly trying to broaden my horizons a little bit on how to improve my code in the future.
Lets say I want to start unit testing. Having pure C# classes that can run this code makes this a lot easier. If I link my animation to my attack code, I now have to provide an animation when testing
I know it's possible with things like play mode tests, but I'm just looking to see if there's any other options
That would take my animation sample into account. So instead of passing the animation, you just delay the execution for a set time, in your case, playmode => animationlength or unit test => default float in your method params
Ye, I suppose just a set timer is a good solution
And then even scaling the animation based on that
Is that how a lot of this kinda stuff is handled in a MVC approach?
Sounds like. I guess some more studied people can help more in this case, as I have no master degree in development or whatever. But from what I read about MVC and guess also doing myself in some cases, it sounds like the approach you are aiming for.
Maybe another example as well, the thing we're actually working on atm:
We're working on a VR game. In that game, we have a machine that crafts things. To craft something, you first have to pull a lever, this plays a "close door" animation, then a button appears. When you press that, an animation is played. After that animation, the item is crafted and given to the player.
There's a lot of things that rely on animations to finish. I guess if you wanted to decouple the animations, you'd make the machine a state machine, that the animation looks at
With timers for every state
Yeh, this is a great example to talk about. So you cant really put your flow of animated interaction to the data. The only thing your data will give your little craft machine would be the item to craft, in this case, right? There is no other connection besides, you decide what to craft, interact with that machine and you get back your crafted item. For me, I only see two data points connected between visual and database, and that is your machine starting and completing. To decouple this even more, you could just send a "CraftTask" to the machine and inside your state controller, you wait for your tasks to be completed.
Ye, indeed
This is what sucks working with only 2 programmers (and the other guy is a junior), I wanna grow as a programmer, but sometimes it's easier to do that when you see other approaches in other projects
I myself did this for an app where you have like conveyor belts and different users can access at the same time and filter out products from that belt. All users send a request to the controller script which then distributes the requests to the belts. All passing around the request, so everyone has one source of truth to rely on
That makes me think of another case, maybe you'll have some input on this. We worked on networked turn based game in the past with Photon. There you have a server set the health of a unit, and the player receives the callback when the health is changed by the server.
How do you deal with delaying stuff there? I suppose you could have an attack command, that you sync to the clients. Server just waits the attack time, clients do the animation when they receive it. When the time elapses on the server, it sets the health, which hands the callback to the clients
You could also think the other way around. What if the server already updated the health for everyone, but the animation will just fire the visual update of the health bar after finishing? If its round based, you do not have to safe check, that something relies on that healthbar like user decisions and what not.
Hm, that's what we ended up doing
The problem we ran into is if there are other things that heal the unit for example
You have to make sure that also executes that logic
But thats totally up to your system, not best practice in that case. Do you want realtime attack and healing, then first come first serve for the server to get the requests (or timestamp based). But if you are doing turn based, you are having a low frequent row of requests which can easily be handled.
I'm not sure what you mean by that
Maybe to clarify on what I mean (and ours is fully turn based): We have an animation event in the Attack animation that says "UpdateHealthBar".
We added a building at a certain point that heals the unit, which had a different animation. Because it didn't have that UpdateHealthBar call, well, it didnt update
I guess you could go around that by just updating the health bar after any unit animation though
So are attack and healing happening at the same time?
no
Okay, i do not really get your health building then. When does it decide to heal or how is it connected to the UpdateHealthBar
Your point was that you could look at the animations the other way around. The server sets the health already, and the client fires a visual update after the attack animation.
This means that you're not hooking into the callback that the health changes from the server, to update the health bar, but instead that something else is responsible for doing that, right?
In this case, the attack animation
Oh, now I got what you mean. Got your point now
Or was that not what you were saying?
You are right about the issue, that your healthbar would only react to the unit. But if your unit gets healing, it will be the same as attack. It plays its attack animation and at the end, update healthbar, right?
Well, for example, in our game, the healing happens when you move on a tile
So there's no attack animation
But ye, its a matter of adding that then to the move animation I suppose
Now you are linking it directly again with the move animation ๐
But aren't you linking it with the attack animation too?
so your player moves to a platform, either the player/unit or the platform will now detect it and send its behaviour, something like HealUnit(Unit unit, float amount) to the server
Indeed
Server then does all the checks, and probably says "Increase health by 10"
oh wait
I see what you're saying
You're saying, client does animation first, then only sends a call to the server?
Only skimming through the conversation, I'd like to say that it's often helpful to separate the true value from the visual representation of the value. Eg when you are losing health, the true health value is decreased immediately, while the health bar receives the event of "health changed" and plays an animation of tweening from old health to new health or whatever.
No, I say, client sends the request, server accepts and sends back result, unit does respond to that result. If the respond is immediately (Helathbarupdate and animation parallel) or in a row (unit animates and then updates visually, just as Burrito just said). the value is updated already, but your unit decides, when to show it visually
Sorry, I know I'm being a bit dumb here, but in the case of row, when you say the unit decides when to show it visually, that is linked to the animation, no? Or there you would also just say "UpdateHealthBar in 5 seconds"
I understand the 2 health values part
Updating the visual healthbar is linked to whatever you decide in code or visually, But it would be OK to link it to the animation time even. Because you are not changing any data, you just presenting it with your unit.
Ye, so for example, if you have a UnitAnimator, you can queue animations on it, at the end of any animation, it calls UpdateHealthBar
And then it syncs the shown health value, with the server's health value
Or an animation event
Exactly
Theorizing code structure without writing down anything is always a hassle
Ye. I love reading books on it, but I always wanna see some actual practical examples
And I've always worked at small studios, where I'm the only coder, or there's someone very junior. I haven't much been in a team where I have a senior with loads more experience
To learn shit like this
But I appreciate your time ๐
I'm gonna go eat lunch now
Enjoy your lunch and I can tell you, I was freelancing for 13 years and learned this on the go, its a lot about reading and just writing code, failing and so on. I am far off from students about what coding principles are there and what not, but still got my things together and learned while working and sacrificing a lot of time ๐ Just keep going and I always live by the standard "There is almost nothing, I cant do or at least try to learn and master it", and so far, it worked out. ๐
Ye, I'm trying to get back into some smaller personal projects. Problem with the studios I've worked at is, it's multiyear projects, which means you're often more stuck in what's already there. New systems can be improved of course, but some things are just a pain to change afterwards
Using Addressables for example, my god. That shit is not easy to retroactively add
changing non async code to async is a pain to start but its a good change.
I much prefer it over coroutines now.
why so ?
async code doesn't require a monobehaviour to be executed and things like UniTask make it easy to just await an addressable asset load and other async things in unity
You either tie your logic to your animation, because your logic is inherently dependent on the length of the animation or you define the length of the animation else where and have your animation respect it.
There is no other possibility here. The first case is better in 95% of the project because it removes a risk of error entirely and reduce the amount of work to do to setup.
many games, not just turn based, all eventually look like virtual machines. if you are savvy, you can still achieve this all in ordinary, pure C# where your game stack looks like a c# stack. this is almost what ECS is.
the depth you need to deal with this problem depends how complex the game is.
specifically for turn based, if your game is resolved in the server, you end up with a marble diagram of reactive messages that look like this
net
msgs ooo
|
obsv o o o
| | |
sel | | |
many o--->o-->o----->xo-->o--->o-->xo-->...
in the select many statement, you enumerate through all the "handlers" of an event & state update in order "with async" or "as a coroutine" i.e., you are waiting for animations to finish until you process the next network message.
because your logic is inherently dependent on the length of the animation or you define the length of the animation else where and have your animation respect it.
you don't have to do this. it's why something like, e.g., a route handler in a website application doesn't need to know which handlers finish, if ever.
it's the same thing
succinctly and correctly writing the code to get a "route handler" behavior for game events and state changes? hard, but it's like 20 lines.
one point of view is that people think all this stuff is decoupled and really it's very tightly coupled. if you look at a web application, the way your route handlers interact with each other is all declared in one place. very, very tightly coupled. and the way you declare routes, pass user authorization information, return responses, etc. is always very opinionated.
At the end, where the length/duration comes from ?
GameMessages()
// Process each message, determining its duration
// The initial message is null
.Select(message => Observable
.FromCoroutine<ServerToClientMessage>((observer, cancellation) => ProcessMessage(message, messageHandlers, observer)))
.Concat()
// code anywhere can now observe the game state
// correctly "delayed" by animations or whatever
.Multicast(m_Messages)
.Connect();
private IEnumerator ProcessMessage(ServerToClientMessage message, MessageHandler[] messageHandlers,
IObserver<ServerToClientMessage> observer)
{
var messageContext = new MessageContext(...);
foreach (var messageHandler in messageHandlers)
{
var processor = messageHandler.Handle(messageContext);
// workaround for https://forum.unity.com/threads/yielding-a-nested-ienumerator-waits-a-frame-even-on-break.772352/
while (processor.MoveNext())
{
yield return processor.Current;
}
}
observer.OnNext(message);
observer.OnCompleted();
}
or await messageHandler.Handle(...)
so the duration comes from however long it takes to process a handler
handlers can see if a message has been "handled"
just like route handlers in a web framework
same semantics
at least if you're familiar with stuff like vertx or even express
it's the same thing
Yeah, and that process needs to happens in that case, meaning that you could not remove the animation from the game to have only the logic running.
the "logic" has already run
in a networked turn based game, everything has been resolved. you get "GameMessages()" immediately
the delay comes from .Concat
If you want to remove all animation of your game. How would that work ?
comment out Select and Concat
nothing in the UI would ever observe GameMessages. maybe i should have written it up as NetworkMessages
i see this kind of thing a bajillion times. people try to animate in a decoupled way
it's impossible
you can still author all of your animations elsewhere, as in this example
this is from my card game
you don't even have to declare the relationship between the animations in the same place
you just have to write 5 lines of code to ensure that the animations are called in an order and with Task or Coroutine semantics
it's a very neat trick
Yeah, hence why I said you either depends on your animation (directly or indirectly) or have your animation respect a duration you set elsewhere.
hmm. there's no duration set elsewhere.
you don't need to know the duration ahead of time
big difference
Yeah, in your case you depends on the animation indirectly. It still needs to happens otherwise your process never ends.
in that example. the duration comes from how long it takes to 'execute' the code. it's a coroutine, so that could be infinite, or zero.
example of showing a little hearthstone damage number popup on cards:
/// <summary>
/// Shows a damage view.
/// </summary>
public sealed class DamageHandler : ValueEventHandler
{
[SerializeField] private float m_Duration = 1.1f;
public override IEnumerator Handle(MessageContext messageContext)
{
if (messageContext.message.Event?.EventType == GameEventTypeMessage.Types.GameEventType.PreDamage)
{
messageContext.HandledBy(this);
yield break;
}
if (messageContext.message.Event?.EventType != GameEventTypeMessage.Types.GameEventType.Damage)
{
var shouldWait = bufferedEvents.Count > 0;
ProcessBuffer();
if (shouldWait)
{
yield return new WaitForSeconds(m_Duration);
}
yield break;
}
var evt = messageContext.message.Event;
Buffer(evt);
messageContext.HandledBy(this);
}
}
it doesn't though
it doesn't need to happen
it could wait, or not wait, or do nothing
it's up to you
it's exactly the same as a web framework
Oh, see here you set the duration.
almost named all the same things
Which would be the more hard to maintains but more decoupled way of doing things.
hmm. the duration here is for the animation from a practical matter, right? but big difference. the network code doesn't need to know how long the animations take
i did want to show you this because it uses the word duration
but there's a big difference here
you could choose to not "yield return"
you can do whatever you want
you can make a change to an animation in the inspector, and everything just works, but the network code, it doesn't need to look inside the animations to know how long they last
animations just happen, or not.
the trick is in turning animation code into observables, and concatting them. the point is to use system.reactivex / unirx to make a bug free "route handler"
I feel like "events" should all get handled together and any required animation changes should happen after somewhere else
because otherwise it's kind of clunky to "delay" game state elsewhere
i mean take it from someone who has written this in a robust way
we've looked at this a million different ways
they do, in those 6 lines of unirx code
that's kind of the magic
people reinvent all of system.reactive to do something like this
oh i presumed this was network messages not internal event messaging to react to it
they end up with a whole implementation of system.reactive spread out across their game
it is network messages...
the network messages arrive immediately
let's say. 100 of them.
okay. lots of people struggle with, i want to program some of my ui to be traditionally reactive, like a website
and other parts, i want animations
so how do i "delay" the "messages"
you know, messages, game state, whatever. it's all the same thing
it's about the developer experience. how do you write something which can show like, the number of hitpoints on a unit without being aware of animations, but also author a damage explosion animation that correctly "delays" the hitpoints going down in the thing that visualizing the hitpoints
you take your network messages, and you never show them to anyone directly
your network messages are processed one by one, checking to see which animations are interested in them
run the animations. it's up to the animations how long they last, or if they should take any time at all, or whatever.
after all the animations are done, update some value, we can call this the local view of the state, that things that need delays but would prefer to not be aware of delays would subscribe to. in fact this is the only view of the game state the UI needs 99% of the time.
this much is clear. everybody wants this. the question is how to implement it succinctly
MOST people spread out an ad hoc implementation of system.reactive across many places
and so it FEELS like this is way more complicated than it actually is, because they don't know about system.reactive / unirx and the problems it solves
the IDEA isn't super simple but it's simple enough
I need to look more into reactive. I'm not very familiar with the way it works
so the pseudocode in the code block. i mean you read that. you think, "i should have a for loop." NO.
But the way you explain it, it does seem to handle exactly what I'm talking about
that is implementing system.reactive!
@echo coral am i making sense now?
the trick here is NOT the idea of how to correctly delay for animations
or whatever
the trick is to know not to ad hoc implement system.reactive
for years people were like "eww unirx"
and now that it's "blessed system.reactive" maybe it will be better
You either set a duration somewhere and utilize that or you use the duration from the animation directly. In both "your method" and "what is used", if the animation is deleted the game does not work any more, in what I suggest it still works. Obviously it requires more work and you should not really do it in my opinion.
nah
it's up to you
everything i'm sharing is from a real game. you want to delete damagehandler component from the game object? great. everything sitll works
but you are overthinking this
i think it's a lot to wrap your mind around because it is so, so succinct
what is "concat"? what is it doing there?
what is turning a coroutine into an "observable"?
why are the game messages being passed down through this, and then back into something called m_Messages?
these are the questions. that's how you implement all of this with brevity and correctly
i mean the real game. the animations are developed one at a time. there are so many of them.
that's the whole point of this architecture
i had to stare at a lot of marble charts to understand this all
dismissing it as an "abstraction" is the worst possible thing you could do
worst takeaway
it's not an abstraction, it's the opposite. Concat, FromCoroutine and SelectMany is the implementation not the abstraction!
just because something FEELS abstract doesn't mean it IS
Mate, stop.
You clearly do not understand what I am saying and you are not trying either.
End of the discussion.
Hm, I'm just wondering if I got it right.
I'm gonna put it into the example of a monobehaviour, I wouldn't implement it this way, but I just wanna know if I got the basic principle right.
Would this be the equivelant of having a monobehaviour Unit
When it executes a method, lets say attack, it searches for all the IAttackHandlers child objects, and awaits the "HandleAttack" method?
Very simply put (and probably oversimplifying)
but listen. there's a reason the cygames guy, who also makes a card, game, and i, use the same thing
so this is just animations
it's up to you. it depends how your game is architected
Like, I'm just trying to understand the basic principle a bit
Of what you're saying
do you want to execute the game logic and the animation in the same place?
well. have you ever developed a website?
i think what you are describing is decoupling things in a way that is spreading out system.reactive in an ad hoc way
I understand its probably much more than what I explained, I'm just trying to pull it to an anology which is closer to my usual workflow
it's kind of the point i'm trying to make. there are a million right ways to do this, but there are only a few best ways
I understand that what you were saying earlier was much more global
so really you start with: where do you want to define these things:
struct GameState {...}
struct AttackArgs {Unit source; Unit target; int damage;}
static void Attack(GameState currentState, AttackArgs args)
static async void AnimateAttack(GameState currentState, AttackArgs args)
attack could look like
static async void Attack(GameState currentState, AttackArgs args) {
currentState.units[args.target].hp -= args.damage;
// check if the target has died
if ...
await AnimateAttack(...);
}
and then, they don't make it static
class Unit : MonoBehaviour {
public async void Attack(GameState currentState, AttackArgs args) {
currentState.units[args.target].hp -= args.damage;
// check if the target has died
if ...
await AnimateAttack(...);
}
}
@hearty shoal okay, you see how this works? i mean this is correct
but do you see. it's up to you where you want to define and call those things
Yup
you can see how, if attack can change currentState at any time, then you have to do a ton of work to update UI in the right places
etc. etc.
if you mix things like this, you can have something that is correct, but it will be very hard to write it correctly all the time
even if it's easy to understand
yes, this is what I was trying to avoid, indeed
so what i am advocating for is to put these things in kind of idiosyncratic places, but the net result is that things become way easier to author
you have no choice but to try to understand system.reactive / unirx
if you want to do things that way
most people eventually arrive at defining Attack and AnimateAttack in different places. you have to, in order to have a networked game for example
but from there. it's a huge struggle to not reinvent half of system.reactive poorly
nearly everyone chooses to do that
in some cases, on top of reinventing system.reactive they also reinvent ECS
@hearty shoal are you trying to make a networked turn based game?
i know the stuff i am writing sounds like crank gobbledygook, it certainly has that energy
Honestly, for simplicity sake, lets say no. Like, this is a problem I run into a lot, the thing you show of having the await AnimateAttack in the attack. I was mainly looking for alternatives for these kinds of issues
I'm not looking for an actual solution, more to broaden my horizons, to explore different methodologies. Like, we're gonna stick with what we have in our current project regardless, but it's more something I want to learn for future projects
well you have to be brave enough to adopt unirx. the thing is you are already authoring unirx
you just don't know that you are doing that
Greenspun's tenth rule of programming is an aphorism in computer programming and especially programming language circles that states:
Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
except "Any sufficiently complicated Unity game contains an ad hoc, informally specified, bug-ridden, slow implementation of half of System.Reactive"
does that make sense?
so you kind of already know the best methodology. it's the one in the pseudocode. you already know what you want
and you are sort of already doing it. it comes down to whether or not you want to stubbornly refuse to adopt some libraries, sometimes, because "dependencies"
it's usually that
like going to your team and adding a "dependency"
that's the problem
@hearty shoal "hey guys, let's add this dependency" --> everyone yells at you
Tbf, it's not being stuborn or anything, it's more ignorance at the moment
I'm open to learn, ye, but I am ignorant of what it is atm
I didnt mean that as a put down :p
i know i know
I'm defo gonna read up on it, I was mainly a little confused at what you said in the very beginning, with the message handlers and what not. I was curious, very high level, how that worked
it's just tough. i think this is why many of the games with the most opinionated engineering have such small teams. it's got little to do with right or wrong per se. but the average person gets stuck at the door with "dependencies" before deciding if something is a good way to do something
yeah without having developed a website it's very hard to understand
because that's what the idea is borrowed from
there are like 100x as many website server backends as turn based games so people have thought very deeply about how that should work
Ye, I imagine often in websites you also have to await an animation to finish, before showing something
yeah. all the time. and then in the backend, well writing to a database takes a "long time"
there's a lot of wrangling stuff that is async and evented
and how to express all of that
But thats why I tried to put it a bit into a more monobehaviour perspective, just to wrap my head around it
Because at the start, you mentioned messages and all that, just curious, very abstractly, how it works
well in my implementation, there is no Unit MonoBehavior
No, of course, of course
and the AttackHandler monobehavior is AddComponent to some random root object, just once
which is the same as declaring your routes in a website backend
once you see how website backends are authored, this is instantly more clear
messages are just "people visiting your website"
sometimes you care about that being handled in order. like if it were a banking website, and everyone was depositing and withdrawing from the same few accounts for example.
so that's what this is all for
you don't want some people to wait to see their correct account balances, but you do want animations on the client.
how do you do all of this? that's where the ideas come from
But high level, without monobehaviours. You have some sort of Unit script, correct?
And I'm guessing that Unit sends a message "I want to attack"?
Then it looks for any handlers that want to react to the attack. You await all of those to finish (In order, or not)
I understand this may be a gross oversimplification, I'm just trying to wrap my head around what it looks like a bit
high level it's a card game, so the client is picking one from a fixed group of actions, and then the server runs a "librarified" version of the game to determine the effects of taking that action
there's no unit script sending messages
there's one entrypoint for taking user actions
k, so there's a script, UserActions
and anything on the battlefield (imagine hearthstone) can emit actions the user can take
yes
it is open source, so you can browse to your hearts desire - https://github.com/hiddenswitch/Spellsource/tree/develop/spellsource-game
I'll have a look
there's also xmage that is implemented in a similar way, but for magic the gathering
But you enqueue this AttackAction. Then it looks for any handlers to deal with that action. And it awaits those handlers?
from the server's point of view, everything is just executed. attackaction has some method on it, it runs, and that kicks off all the game logic, there's no waiting
as the game logic is executed, events are raised. these are just structs that snapshot the game state and have some extra info. so dealing damage, but all the other things that could happen in a card game like hearthstone or magic
something gathers up these structs and sends them to the client
the client receives them all immediately. one by one, the client looks at the struct and finds MonoBehaviors called Handlers that are interested in the struct, and await handler.Handle(theStruct)
all the animations are authored in Handlers
Ye, so you might have an AnimationHandler, and a PlaySoundHandler
this way they all happen in order. since the Handle is awaited, all the durations can be dealt with without knowing how long it actually takes
yes
and since it's async, you can choose to wait or not inside the method
Client receives the AttackAction
client gets all the events all at once
in microseconds
because that's how long it takes to evaluate teh player's choice on the server
all at once, but in order.
so it has a full snapshot of the journey of the game
up to the point that a player needs to make a choice
Can you clarify what you mean there? Events here being the actions?
client receives a list of possible actions, like attackaction, end turn action, whatever. then it tells the server, i want action index 0
Ye, sure
actions -> things the player decides to do
events -> i choose in the game engine, here are things i care about to visualize and/or are important to executing a card game. such as "a unit took damage" "a card has been discarded" "a card was drawn" etc.
I see, so for example, player sends attack action to server
Server translates that into: Oh, so that's damage to the unit, and then it ends the player turn. So client receives event: Damage unit, end turn
based on those events, client looks for related handlers, and awaits them?
I'm guessing there's also an attack event?
For things like animations of the actual attack
yes, and that gets animated into one unit smashing into another
So client receives "Attack Event", looks for handlers:
"PlayAnimationHandler", "PlaySoundHandler", it awaits both of those
Once its done awaiting those, it moves on to the Damage Unit event
awaits stuff there
(if you want it to wait for each other)
yes
BUT the thing that is written on the unit that says how much HP it has
it finds the unit in teh game state and subscribes to changes in its hp
the "game state" that it subscribed to is updated "after" "every handler"
it never sees the instantaneous stream of events
so there's a bajillion places in the UI where things would be clunky to express as handlers.
Ye, thats fair
so yes. that's it. that's the whole idea
But I wonder, how does it handle things like updating the health after an animation?
If its not handled by handlers
you can do that in your for loop
if you wanted to
you could do this.healthChanged(...) in your for loop, and things can healthChanged += it
The for loop of taking in the events? What for loop?
foreach (var event in events) {
foreach (var handler in handlers) {
await handler.Handle(event);
this.gameState = event.newGameState;
this.gameStateChanged();
switch (event.type) {
case DAMAGE:
this.unitHealthChanged(event);
break;
case ...
}
}
}
yeah
you can do this
I see
okay. so now we're fleshing out all of the code to do this, you see that it's not so simple, this implementation
you certainly CAN do it. but it's reinventing UniRx / System.Reactive ๐
But those are libraries that implement this paradigm, right
uh they just deal with all the problems this can solve
correctly
you know that drake meme
he's saying "no no" to system.reactive
and he's nodding yes to "doing this all yourself crappily"
because people use hating dependencies as a coping mechanism for how hard programming is
and hard programming means you don't make your game
you can write "event bus" into the discord search
and see for yourself. people love writing event busses
Well, I do think there's value in writing it yourself to understand how it works
Well, I appreciate you taking the time to explain this all
hello i have this huge climbing system script and i have some bugs can anyone help me?
well this is it: https://paste.mod.gg/iuozmoqssnde/0
player just snaps down when walking off a tall building..
A tool for sharing your source code with the world!
!code
๐ Large Code Blocks
Use links to services like:
https://paste.mod.gg/, https://hastebin.skyra.pw/, https://paste.ofcode.org/, https://paste.myst.rs/, https://scriptbin.xyz/
๐ Inline Code
Surround code with three backquotes. Not quotation marks.
To format as C#, add cs to the first line:
```cs
// Your code here
```
Add a comment with a line number if there is an error message.
my apologies
what is your opinion to the best Method to create a dash ability
The method that moves my character in a direction at a speed
switching on enum values is a big code smell for me. instead of iterating over so much stuff agnostically and checking every type every time, queue them in a dictionary of lists using the enum as a key
this is just a different way of doing the same thing. This is less expressive, though.
The dictionary approach cannot enforce exhaustiveness. Not in C# anyways, in languages with a more powerful type system like TS, you can.
wait what TS being a more powerful type system than C#?
Way more powerful, TS type system is Turing complete.
they certainly get fancier with them
the problem is at some point it has to become js
Building off js I wouldn't expect* the exact opposite to happen
so you don't get the crazy runtime type magic that C# does
Typescript's type system is sooooooo good
You can use generics to modify the state of whole objects. Like Required<T> removes all nullabillity on objects. Imagine that
The type system doesn't have to be constrained by runtime, in fact the JS runtime being "typeless" actually allows you to do a lot of interesting patterns in TS, that is otherwise impossible to do in C# without sacrificing type safety/having to resort to source generators to get type safety back.
I'm not knocking it for that. I understand that the type system being constrained by runtime safety makes it less feature-complete -- that's a given haha
the utility types for instance are freaking insane
when you start to toe the metaprogramming line is when you really start to miss the runtime stuff (or at least, I do) -- even little things like reified generics are hard to part with ๐ฆ
RTTI vs type erasure is definitely an interesting language design choice, both have pros and cons.
For sure, I definitely feel like from a "correctness" standpoint, you'd lean towards erasing type information.
If your entire codebase is fully and meaningfully specified, you don't ever NEED that runtime type information. There's always a better way to do it.
Reified generic for example, in C#:
T Create<T>() where T : new()
{
return new T();
}
Can be roughly thought of as Create(Type t), but the problem is that there isn't a way in the type system to express "that function returns whatever an instance of Type t"
In TS, there is a way to express that in the type system:
function create<T>(cls: new () => T): T {
return new cls()
}
In general, languages that use type erasure go with the approach of "passing runtime objects, and use the powerful type system to infer types."
Even in this example, one of the unfortunate effect is that C# only has where T : new(), so it cannot express something like "T is a class that can be constructed with a string parameter" whereas that is possible in TS via:
function create<T>(cls: new (arg: string) => T): T {
return new cls('hello world')
}
The same has to be written in C# using a factory method wrapping (arg) => new MyClass(arg).
Yeah, for sure. i prefer a healthy balance between both tbh
Sometimes you need to interact with systems that come from a less refined type system than yours. Maybe it's serialization, or a poorly typed library, or even just legacy code.
That's when I start to really miss the cheats we get from rtti
Yeah you just need to be flexible and make use of the strong points of the language you are using. C# source generator is great and makes up for the situations where the type system is not powerful enough, TS type system is powerful and makes up for situations where you do need runtime type information.
Have you used Hack at all? I think they struck a really good balance there.
Honestly anytime I code in anything else I just wish it was more like it haha
But it kinda does a little of both. There's really complete refinement available at static analysis (less so than TS, ofc). But then it also keeps parts of that at runtime
So you're given some of the goodies from each side
I'm comfortable working with both C# and TS that they together covers pretty much all use cases (bar embedded) that it's hard for me to get into a new language. Not for the lack of trying, but I pretty much just forget whatever new language after a while because there's never a chance to use them ๐
Yeah yeah I totally feel that. That's how I feel about rust actually, it looks really cool, I'd really like to play with it. But I'd just never get to do more than that with it
Quick explorative question: i'm looking into how to further optimize my procedural terrain rendering. I'm currently computing my vertex heights on the CPU (using jobs+burst this is lightning fast on a Ryzen 3700X 8 core, and even negligible on an 8th gen intel 6 core), but then I'm also constructing a whole bunch of actual meshes based on the heights, all on the CPU. I'm probably going to keep my noise calculation on the CPU but I figure if I can just send those heights to the GPU in a buffer and render them all using some instancing command, I can save a ton of bandwidth (1 float vs 3 floats, and I can probably even use halfs for it considering my height data is in the range 0.0 to 6.0, so that's a 6x memory reduction) and move a whole lot of super parallelizable execution to the GPU. I think I should be able to use Graphics.RenderPrimitivesInstanced() (API) for this, because it gives access to a vertex index but I'm not sure if it's possible to get like full control over the data on the GPU, like chunk position offset or other data that can be global for a specific draw call. One thing I've never looked into Custom Render Passes, but I figure this would be the most logical place to put rendering code (I'm doing other instanced rendering in this project in a MonoBehaviour.Update call). So my question is: for this use case, can it be beneficial to render things like terrain 'meshes' in a Custom render pass?
Ive been exposed to javascript just by virtue of being cheap and not wanting to pay to make a portfolio site lol. That and gives me an excuse to practice css which is gonna help with ui toolkit
rofl, except that css works and uss is a heap of shit
Moms like we have css at home
dont know what you mean by that but best of luck tracking down errors you make in uss
You dont know the meme of "mom can i get X?"
Mom: we have X at home
Then it shows a picture of a really shitty version of said thing
I love explaining jokes it makes them so much more funny lol
I don't do memes, way to old for that childish shit
amazin
I think I finally set up an input system that I'm happy with btw. pretty hyped. So unity's new input, using c# events and generating a c# class for the input controls, instantiate it in a singleton and bind it to static event containers. End result is really simple event binding
private void Awake()
{
_mainCamera = Camera.main;
InputEvent.Ui.Click += OnClick;
InputEvent.Ui.Point += OnPoint;
}
private void OnDestroy()
{
InputEvent.Ui.Click -= OnClick;
InputEvent.Ui.Point -= OnPoint;
}
https://paste.myst.rs/jlvvjioc if anyones interested in the full implementation. just used the default action map for now but will inevitably be tweaked im sure
I prefer to just make the singleton a dumb instance container, making the single instance available to any other script. Then those other scripts can do whatever they like with it - subscribe to events, poll it in Update, whatever.
I feel you. I don't like needing people to access the singleton though necessarily, and there's like low low chance of race conditions accessing it directly, whereas having static events that the singleton binds to when its ready is like super idiot proof. and the event containers are just to make it tidy
and i'm making my first proper game in DOTS so im big idiot mode right now lol
something i realized about DOTS though is that it's like insanely unit testable so i'm really going hard with the testing
something i started doing recently btw - I got really used to having like friend class usage in my c++ projects and I wondered why C# doesn't use it until i realized it kinda does
with explicit interface implementation. narrows usage of a class only to things that know of it as that interface, like obviously any interface has those defined members, but if you have an explicit interface implementation, those members are hidden from things that don't reference it as that interface
stranger can't boop my dog cause he don't know him that way
thought that was really neat. gonna be using that a lot more
so you can do really cute stuff like have highly mutable types but the interface to manipulate them is sealed to the module
Using a phone as a golf club
I am using Input.gyro.attitude. Looking at the gif, the golf club is swinging in a circle around the player at an angle. From the gyro attitude, I need a way to get the degrees per second that the phone is rotating.
I am thinking that I need a way to get the circle of best fit.
Additionally, I need to know if the last frame of input before the ball is hit is under or over the best fitting circle, as well as its distance to the circle. That way I know how much the ball is gonna curve left or right
Any help or direction will be greatly appreciated
you're gonna have to buy a lot of new phones if you're hitting balls with them
Gif
so you need more than just attitude right? i assume you're holding the phone like a club?
Yes
its tough too cause you gotta account for wrist movement, even if your accounting is that you don't care lol
I assume I can use the attitude to calculate the speed of rotation
not if they flick their wrists you can't
Maybe the accelerometer is what I should use
yeah i think so
accelerometer will let you track its actual delta position per frame and you can reverse engineer a circle which will let you calculate arc seconds
that's called dead reckoning and it's not particularly accurate at this scale
I see. Then I am stumped ๐ค
so you want tangential speed AT point of impact OF the imaginary club head which is a fixed offset from the phones positive Y axis or something like that
honestly i think the best solution would be to have some kind of attachment mimicking the shape of a golf club to get the inertia and moment right, and it'd also help prevent accidentally flicking the wrist
kinda like wii tennis attachments, just a foam tennis racket to get the feel right
but that's probably not practical
i think you'd have to choose what you want to focus on
the rotation aspect, or the hitting aspect
for the former, you'd primarily check rotation
for the latter, you'd primarily check acceleration
accounting for both seems like a pain with diminishing returns
actually wii does have golf
maybe that could have some insights
Quaternion rotation = Input.gyro.attitude;
Vector3 clubOffset = new Vector3(0, -ClubLength, 0);
Vector3 clubPosition = transform.position + (rotation * clubOffset);
Vector3 acceleration = Input.acceleration;
float speed = acceleration.magnitude * Time.deltaTime;
float angularSpeed = Input.gyro.rotationRate.magnitude;
float tangentialVelocity = ClubLength * angularSpeed;
i think? you could do this in update, cache the tangential velocity and apply it as explosive force to the ball on impact
the real question i guess is how much does aiming matter? or are you more looking for just like effective form and motion
also i think that should be localposition where i'm calculating the offset there but you get the gist
wii sports golf only used a linear accelerometer, no gyroscope
they probably just do simple speed calculations and clever movement restrictions and checks to see if the gesture is somewhat correct
like "is y trending up"
iirc you could just flick and it'd have the same effect as a full swing if you got the strength right (presumably just checking tangential speed at impact, like you mentioned)
and then they just output the accelerometers deltaZ to the player hand
yeah that's why i wouldn't use rotation by itself it's super exploitable
@jaunty creek what you could do is create a small gesture test suite where you can iterate on those parameters. define like a GolfSwingGesture, then you can boot up the unity test and just practice swinging and see if the light goes green when you expect it to
if you wanna be real fancy you can machine learning the heck out of it lol. sit in front of your computer all day swinging your phone for a week and then it's like alright bet i know what a golf swing is. Then you just check IsGolfSwingGesturePerformed() ? ApplyForceToBall();
you would also have to do negative samples
My bad, I thought I was in shaders lol
Indeed. This makes it very easy to move away from a singleton instance when needed
You just replace every instance of Foo.Instance
(that's one hell of a load-bearing "just" ๐ )
The even easier way would be to have a service locator singleton and ask it for an instance of an interface
@humble loom & @drifting solstice Thank you both for the suggestions. I'll try fiddling around with a few different ideas and pick the one that seems to work the best. I will not try the machine learning thing though ๐
But what about wii sports resort? I think that it only uses the gyroscope, as you can do it with a flick of the wrist. Also, it can be done no matter the orientation (lying down, pointing downwards, pointing upwards)
i wasn't considering the motionplus before (nor the switch) because i was thinking of like, the simplest solution
i'd wager a guess that the motionplus used both
That sounds about right
for the machine learning thing, let's say, 1 swing/sec, nonstop, for a relatively small sample size of 2000 (1000 pos, 1000 neg) you would have to sample for 33.3 hours
2000 here being small because of the sheer amount of variation possible
for a decent & reliable sample, it'd probably be a few month's worth of manhours lol
Ahah. I like the math way better ๐
Wait, one swing/sec for 2000 seconds?
That's about half an hour
I could do an hour or two ๐
But math is still cooler ๐
does anyone know the absolute fastest way to bake a collision mesh? in physx or unity physics
VFX graph has a nice SDF tool but no clue if you can use it outside of its intended usage
well doing it at import time obviously the best, otherwise disabling some checks should speed it up if you need it fast during runtime immediately https://docs.unity3d.com/6000.0/Documentation/ScriptReference/MeshCollider-cookingOptions.html, or doing it off the main thread if you're trying to avoid frame hitching https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Physics.BakeMesh.html (see bottom section)
whoops read the result wrong lol.
in my defense it was very late at night
is there any quick '() => ' syntax to make an enumerator
if the return type of the delegate was IEnumerator that could maybe work?
ye just figured it out, that was silly of me ๐. Thanks
yay easy fix
is there anyway for me to reference a script asset directly in the inspector
er what do you want to do with it? probably not unless its a custom inspector referencing an asset object
im just trying to see if i can reference a script and execute a method in it
not how it works, it references a monobehaviour instance
not the script asset file
ye and im trying to see if i can reference a script asset and execute
you just cant
it needs to be an instance on a game object. If its a scriptableobject then it needs to be an instance of one too.
is this script a monobehaviour?
can i reference the script asset if it was monoBehaviour?
you can but it's not very useful
you can reference it but you can't really do anything with it from there
@brisk spear what do you hope to do and perhaps we can think of an alternative
im just trying to see if i can reference script asset directly to use as a drag and droppable delegate
i know i can make one time scriptable object as delegate so now im just trying to push further
MonoScript isn't even available in a build
what is the overall "goal" though or is it just experimentation?
You could technically record the class name and use reflection at runtime to locate and call shit but not ideal
just experimentation thats all