#archived-code-advanced
1 messages ยท Page 104 of 1
very little
if i have this same component on around 100objs
mostly it takes up memory
well, then shouldn't be a problem
but it will be a component that needs to be iterated over for GetComponent and things like that
its hard to quantify
depends on what you're doing
etc
i'm calling getcomponent on those 100 gameobjects only several times per minute
and at different circumstances
I keep getting the following errors when I try to perform UNDO of assignment to a serialized property with [SerializeReference]:
Could not update a managed instance value at property path 'managedReferences[2082630382636761095]', with value 'mylongpackagename.BirpShaderPreset'
UnityEditor.EditorApplication:Internal_CallGlobalEventHandler ()
I tried following this guide: https://docs.unity3d.com/ScriptReference/SerializedProperty-managedReferenceValue.html
hmm, it may be due to the prefab stage
In Model-View-Presenter Architecture : MonoBehaviour or POCO (Plain Old Class Object) ?
Hi! I'm working on a steam multiplayer game.
I don't know if this issue is simple or extremely complicated. But basically, when I host a lobby in the unity engine it self or just generally launch the game (Using the space wars id: "480") everything works perfectly. After building the game however, hosting a lobby doesnt work and the steam app doesn't recognize I launched the game. But it does recognize it in the engine.
I did open steam and go to my profile before launching the game. That makes it even more confusing.
do you still have the editor running? it's possible steam is still considering you ingame in editor, in which case it won't work in the standalone build usually
Let me quickly test it out
basically make sure your steam status doesn't show the game before you launch the build
nope doesnt work. the steam status doesnt show the game is launched
in that case i would guess it's most likely not getting the correct app ID for your app, you should normally hardcode it in the game but try adding a steam_appid.txt file into the build folder?
like set the app ID in code, where are you setting it now?
OK, it depends on the plugin
there's a common older method which looks for a config file in the game folder
hm whats the new method?
can you check the logs in the build then, it's likely the steam plugin is failing to initialize for some reason
it depends on the plugin you're using
didnt give any errors in the build.
log
so you can see it's initializing successfully?
and it's still not showing up in steam?
yes
then it's not initializing successfully ๐ค those messages don't look like they're coming from the steam plugin, make sure you're logging the result of that
you can turn on the player log in the build settings
whats the option called? (sorry I haven't turned on the player log before..)
it's in the Player settings, "Use Player Log"
it's turned on
Aight. What do I look for?
i don't know, i don't use facepunch, errors i guess?
it opens in a notepad. I will give it a read.
Aight. So I'm getting the error: "Object reference not set to an instance of an object"
nothing related to steam tho. The error is from a steam manager script though
that sounds pretty related to steam to me ๐
Ouchie. The error doesn't show up in visual studio tho
Do I send you the script?
does the log not contain a line number?
make sure stack traces are turned on the player settings too if not
I'm not sure. I am staring into notepad. Do you see anything?
NullReferenceException: Object reference not set to an instance of an object
at Steamworks.SteamMatchmaking.CreateLobbyAsync (System.Int32 maxMembers) [0x00014] in <19bd4cc6a4004258bf538b05ac1133d6>:0
at SteamManager.HostLobby () [0x0005b] in <5deda5957ad641ba8b1b7e832b67ef7b>:0
at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in <467a840a914a47078e4ae9b0b1e8779e>:0
at UnityEngine.UnitySynchronizationContext+WorkRequest.Invoke () [0x00002] in <6ef01846f2094996aa9c77a64b17827d>:0
at UnityEngine.UnitySynchronizationContext.Exec () [0x0005d] in <6ef01846f2094996aa9c77a64b17827d>:0
at UnityEngine.UnitySynchronizationContext.ExecuteTasks () [0x00014] in <6ef01846f2094996aa9c77a64b17827d>:0
I know where this line is in the code.
everything seems to be working fine in visual studio
Make a development build.
yeah, the easiest way is going to be attaching the debugger
that will give you actual line numbers and file names
and you can also attach a debugger
Okay! Let me do that.
aha! When I host a game im getting the same error. "Object reference not set to an instance of an object"
seems like the error is in this line of code. @stuck plinth @bleak citrus
public async void HostLobby()
{
await SteamMatchmaking.CreateLobbyAsync(4);
}
it's in CreateLobbyAsync
there's actually nothing on that line that could throw an NRE, unless SteamMatchmakingis actually a variable (which would be weird, because it's also either a namespace or a type name)
right, and the problem is inside CreateLobbyAsync
This stack trace said that the error happened in CreateLobbyAsync
Yup
So you need to look...there
it's one line of code. nothing wrong shows up
so why are you looking at HostLobby?
I'd bet that steamworks isn't being initialized properly if createlobbyasync is throwing
because its what gets called after clickign on the button
This is not CreateLobbyAsync. This is something that calls CreateLobbyAsync
their aren't any errors in the log though
the stack trace says that HostLobby called CreateLobbyAsync
"isn't being initialized" could mean that nothing is happening at all
Are you certain that whatever code initializes it is actually being called in the build
im pretty certain. Everything is working perfectly in the editor. But doesn't in the full build
How have you confirmed it is being called
is the version of facepunch im using outdated or something?
Hence why boxfriend asked you
i did a developer build. it kept giving me this error:
NullReferenceException: Object reference not set to an instance of an object
at Steamworks.SteamMatchmaking.CreateLobbyAsync (System.Int32 maxMembers) [0x0000f] in D:\a\Facepunch.Steamworks\Facepunch.Steamworks\Facepunch.Steamworks\SteamMatchmaking.cs:155
at SteamManager.HostLobby () [0x0001b] in D:\UnityGames\Beyond The Ice Wall\Assets\Scripts\SteamNetwork\SteamManager.cs:67
at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in <467a840a914a47078e4ae9b0b1e8779e>:0
at UnityEngine.UnitySynchronizationContext+WorkRequest.Invoke () [0x00002] in C:\build\output\unity\unity\Runtime\Export\Scripting\UnitySynchronizationContext.cs:153
at UnityEngine.UnitySynchronizationContext.Exec () [0x0005d] in C:\build\output\unity\unity\Runtime\Export\Scripting\UnitySynchronizationContext.cs:83
at UnityEngine.UnitySynchronizationContext.ExecuteTasks () [0x00014] in C:\build\output\unity\unity\Runtime\Export\Scripting\UnitySynchronizationContext.cs:107
(Filename: D:/a/Facepunch.Steamworks/Facepunch.Steamworks/Facepunch.Steamworks/SteamMatchmaking.cs Line: 155)
This is not what I'm asking about
one of the reasons for this is that scripts can be run if a different sequence in a build. Hence the question
the point is that Steam Matchmaking may not be getting initialized correctly, causing an error to be thrown when you try to create a lobby
how have you confirmed that SteamClient.Init is being called
you need to prove that it works in the build
Hm, Since it's not giving me any errors or anything in the log, seems like it hasn't been confirmed
This is my first time with networking.. Can you tell me how do I do that?
right. you need to actually verify that the steamclient is getting initialized
use logs or breakpoints
this has nothing to do with networking, really
i'm asking you to prove that code runs
that's it
Let me try a debug.log
to make sure its running
breakpoints >>> debug.log
it isn't being called.
Well there you go, that's why you're experiencing the NRE in CreateLobbyAsync
So, steam is working in the editor but not in the build.. But why, is the question
I don't think I have experienced this before and I've been using unity for a long ass time.
Hm.. I will take a look at that, thank you!
Well how/where are you even initializing the steam client
It's getting initialized via steam manager script. Which is connected to a button that calls the method "HostLobby"
Ah yes the "steam manager script". That definitely tells me how and where it is being initialized since I'm super familiar with your code
And where do you call SteamClient.Init
shit, did i actually forget it?
what? So much for 'the code works in the Editor'
I added the code.. Still having the same issue. This turned to a rant at this point.
I don't even see there where you call HostLoby
line 70
oh you mean where you call it? I call it via a button
so what is this line?
Filename: D:/a/Facepunch.Steamworks/Facepunch.Steamworks/Facepunch.Steamworks/SteamMatchmaking.cs Line: 155)
This isn't in the steam manager script. It's from the default facepunch script
yes, and it's the line of code throwing the null ref exception.
I honestly think that someone who has used Unity for 'a long ass time' and is posting in code advanced would at least have a modicum of knowledge on how to debug
Yea, this is pretty humiliating.. I haven't touched unity in months because of the recent events.
I'm sorry for wasting your time.. I will have a full dive into this right now.
I have a big problem with nav surface. When adding/removing buildings in the game, I update nav mesh surface but it considers just previous buildings not the current one even though I delay one frame and call update nav mesh method in LateUpdate!
private void LateUpdate()
{
if (!_isDirty) return;
_isDirty = false;
UpdateNavMesh();
}
[Button]
public void BuildNavMesh()
{
_navMeshSurface.BuildNavMesh();
}
[Button]
public void UpdateNavMesh()
{
_navMeshSurface.UpdateNavMesh(_navMeshSurface.navMeshData);
}
private async void OnWorldCreated()
{
await UniTask.Yield();
_worldCreated = true;
BuildNavMesh();
}
private async void OnNavMeshUpdated(Structure structure)
{
if (!_worldCreated) return;
await UniTask.Yield();
_isDirty = true;
}
And where do you call UpdateNavMeshData ?
Calling in LateUpdate
not what I asked
When yielding three times it would be OK or wait for 1 seconds
read carefully what I asked
Why is it so messy? I mean the API. I have faced this situation in UI layout as well (content size filter, change the layout size)
I said inside UpdateNavMesh, so in LateUpdate
public AsyncOperation UpdateNavMesh(NavMeshData data)
{
using var builderState = new NavMeshBuilderState() { };
var sources = CollectSources(builderState);
// Use unscaled bounds - this differs in behaviour from e.g. collider components.
// But is similar to reflection probe - and since navmesh data has no scaling support - it is the right choice here.
var sourcesBounds = new Bounds(m_Center, Abs(m_Size));
if (m_CollectObjects == CollectObjects.All || m_CollectObjects == CollectObjects.Children)
{
sourcesBounds = CalculateWorldBounds(sources);
}
builderState.worldBounds = sourcesBounds;
for (int i = 0; i < NevMeshExtensions.Count; ++i)
{
NevMeshExtensions[i].PostCollectSources(this, sources, builderState);
}
return NavMeshBuilder.UpdateNavMeshDataAsync(data, GetBuildSettings(), sources, sourcesBounds);
}
what?
private void LateUpdate()
{
if (!_isDirty) return;
_isDirty = false;
UpdateNavMesh();
}
public void UpdateNavMesh()
{
_navMeshSurface.UpdateNavMesh(_navMeshSurface.navMeshData);
}
is what I see in your code
I want to use explicit fp16 flag and this is only possible with DXC, not with fxc.
So fricking confused rn can anybody help
Can I keep plants in my game static so it doesn't change position (so no lighting change or navigation change) but rotate it a bit so it feels like there's movement?
No. Static objects can't be moved or rotated at runtime. You'd usually have them "move" via a shader.
Though, I'm not sure if that's possible with static batching(assuming you're using built-in rp)
Is there a way to have polymorphic ScriptableObjects show up in this menu or something similar?
I thought that did work
Yeah, this works fine for me in 2023.2.20f1, at least
This is how I have it set up right now
if I serialize a Foo, I can pick a FooChild from assets
and Foo is abstract (that shouldn't matter)
Ah
Remove [SerializeReference]
That's not meant to be used with anything deriving from UnityEngine.Object
You can serialize references to polymorphic Unity objects with no extra work
since you're really just serializing a GUID
Still doesn't work
Non-Object types get serialized by value normally, unless you use [SerializeReference]
Do you have any actual instances of TestObject in your assets?
Do you have assets that actually exist as derived classes of this SO?
I noticed you don't have a [CreateAssetMenu] attribute
well then you won't see anything!
Is there a purpose to this class even? It looks odd
you're serializing a reference to a specific object
you must have an object to refer to
I'm gonna be loading an array of objects at runtime so modders for my game can add items and stuff via json, this is for the specific data type that's being loaded
I'm not really following.
Do you know Minecraft data packs?
Sure.
I'm trying to do that
So what exactly is RuntimeLoader going to do with this obj field?
When RuntimeLoader is Ready(), it'll tell the RuntimeLoadedObject to either fetch already-loaded data or load the data from disk if it that specific subclass hasn't loaded yet
you're trying to reference a type here, it sounds like
e.g. you want to be able to punch in TestObject into that field
Kinda, yeah
but that field holds an instance of a RuntimeLoadedObject
so that doesn't really make sense
I'm still having trouble seeing how this would work.
I also want there to be data that's not loaded at runtime so I can create them in-editor
Will all of the child classes of RuntimeLoadedObject be the same (so, empty?)
If you're just looking for an identifier, you can make a single ScriptableObject class and then create one instance of it for each "thing"
That's sort of what I'm doing for my game's settings. Each setting is a ScriptableObject asset.
I have a few kinds of these assets (float setting, choice setting, toggle setting)
They'll fill out certain methods and stuff
this is still too vague for me to give a good answer for, then
I have a different idea for how I could do it
It sounds like you want to be able to list:
- The kind of thing you're going to spawn
- An identifier for the thing you're going to spawn (so that a modder can target it)
I'm not "spawning" a thing, per se
You could create one ScriptableObject class for each kind of thing, and then one instance of it (stored as an asset) for each identifier
e.g. you could have a ChestLootDefinition class that knows how to parse a JSON file and generate a loot table to be used by a randomly spawned chest
you'd create an instance of the asset with an identifier of "tier-1-dungeon", and you'd use that asset in your dungeon scenes
There will be a type of item called a Trinket, which is purely a statistic modifier (sort of like badges from Paper Mario)
The player's inventory will have a list of all available trinkets (with duplicates), and a list of enabled trinkets.
There won't necessarily be an instance of that in the node tree, but the effects of it will need to be accessed from different places in the code
You could also directly author the loot table in Unity
What do you mean by identifier?
Each asset would represent a specific instance of something
a specific kind of trinket, for example
the identifier would be a string that uniquely identifies that kind of trinket
Although, this would mean that modders couldn't introduce completely new kinds of trinkets
because they wouldn't have a way to put more assets into your game
hm, this needs some more thinking
You can do away with these ScriptableObjects and work entirely with string identifiers -- and then keep all of your Trinket definitions in JSON files
Yeah bit I want to be able to edit the built in ones in the editor
so when you read the JSON, you're going to deserialize it into a TrinketDefinition or something. if you make that class unity-serializable, you can store a List<TrinketDefinition> somewhere
<@&502884371011731486> looks like someone is looking for a ban here
hey, so i am using mapbox and unity together. i want to make a dragging functionality but its lagging really badly. the latitude and longitude is updating in the inspector but for some reason its taking a lot of time to update in the map - more like its not happening smoothly and is glitching/lagging
sending the code below
I mean doesn't it need to do a web request every time you change something?
Web requests take time
it does but it goes back and forth and becomes really laggy
is there a way to optimize it?
Use the profiler to see what's going wrong
Share the hierarchy view
It looks like it's "other" by the color, so I'd bet on it being the editor loop.
this one?
No... In the profiler.
Check the manual on how to work with the profiler
https://docs.unity3d.com/Manual/Profiler.html
Check the manual. There's no point in this discussion if you don't understand what we're asking.
Also, you just disabled the other category from being shown
alr
yeah
lemme check the doc and get back to you
okay so this is the hierarchy view shown at this frame
@untold moth
Ok, yeah, so most of it is the editor loop. What was the question again? There doesn't seem to be a performance issue in that screenshot
its lagging when i am dragging the map. its imported from mapbox and the code was provided above, the latitiude and longitude is updated in the inspector but its lagging and glitching when its in the game view
Then provide the profiler data for the timing of the lag.
Select a frame that has the lag spike
This is just 20ms. It should still be around 50fps, so I wouldn't call it "lag". But anyways, the cause is the editor loop. Unless you want to fix the performance in the editor, you should test and profile a build.
hmm, more than lag, its becomes really glitchy. is it because its continuosly calling the mapbox api ?
Define "glitchy"? Is it even related to performance?
wait can i send a recording of it?
@untold moth
i think its because its calling the api each time?
Yeah, I'd guess that it's because of how you implemented the api and how it works.
alright
I didn't work in UE, but does it compile this long even if your project is properly split Into separate compilation units?
Whats the proper approach to drawing in sceneview when you're writing an overlay?
I want to draw lines and stuff from an overlay but it doesn't seem to play nicely with handles
Is it possible to get which slider is changing when you setup dynamic value passing in the Editor view only?
I have a audio menu script on the parent a few levels up, and would like to know there which children got changed.
Not possible, no. You'd need to do some kind of workaround
thx @sly grove, as usual. I thought so. Probably code my own delegate there
I need a little help please .
Currently using cinemachine for my camera.
When moving up and down stairs there is this stuttery jumpoing motion happening with my character. I'd like to smooth this out and hav the player move up and down the stairs smoothly without that jittery jerking motion.
My curreht method to actually get movement up stairs is as follows :
void AdjustForSlopes(ref Vector3 movementDirection)
{
RaycastHit hit;
Vector3 rayStart = transform.position + Vector3.up * 0.1f;
float rayLength = characterController.height / 2f + 0.1f; // Use half character height for ray length
if (Physics.Raycast(rayStart, Vector3.down, out hit, rayLength))
{
float targetHeight = hit.point.y;
float currentHeight = transform.position.y;
float smoothedHeight = Mathf.Lerp(currentHeight, targetHeight, Time.deltaTime * 10f);
// Adjust movement direction to include smoothed vertical movement
movementDirection.y = (smoothedHeight - currentHeight) / Time.deltaTime;
}
}
Give your staircase a flat ramp collider instead of a stair shaped Collider
Otherwise use some advanced IK animation stuff
Ya, so I just read about that, but when I apply my custom collider the scale just goes wack
Idk what that means but it sounds like a mistake you're making
Wdym by the scale going wack
when I apply the model to the staircase mesh collider, it becomes huge and the rotation is wrong
They are both at origin
because your meshes are in different places and different sizes
Fix it in blender
I did
You can even see in this screenshot that the blue arrow for the red stairs is facing upwards
So the meshes are all out of wack
Super strange. In maya they are fine. Give me a sec. Thanks for the info!!
Anyway fixing your meshes is going to be much easier than some complicated character controller that handles stairs
for sure ! Thank you
Solid Spot! I would have never seen that my stairs axis was wrong compared to all the other pieces. I made the stairs from a flat plane that I rotated. Thanks a bunch
nice
Honestly I would probably have just cobbled the collider together out of a few BoxColliders and called it a day
that looks like it can be convex though, thankfully
Ya, Now I can create simple colliders in maya. First time doing this though.
Can someone versed in ocean simulation explain why my ocean mesh is too "pointy"? I'm following this paper ( https://people.computing.clemson.edu/~jtessen/reports/papers_files/coursenotes2004.pdf) by Jerry Tessendorf and I thought I implemented everything needed at page 9 but apparently not. It seems that the even vertices are only interacting with other even vertices and likewise for the odd vertices.
Here's a point-filtered greyscale heightmap and what I'm trying to get.
I've tried bumping up the resolution but the dithering persists.
Looking at it a bit more, it does seem that when it does sample the height map of a greater height that the neighboring verts collapse into a lower height than what's represented on the heightmap.
I'm completely and totally at a loss, there's nothing wrong with my animator.SetTrigger or animator.SetBool, the both work outside of the code I'm using here, but when I run them in these functions they don't fire at all.
the conditionals below and the logs inside all fire as expected, except for the animator methods?????
private void TriggerAttackAnimation() {
Debug.Log("Starting playerAnimator debugging");
playerAnimator.SetBool("DebugBool", true);
playerAnimator.SetTrigger("DebugTrigger");
Debug.Log("Finishing playerAnimator debugging");
string currentStateName = "Movement";
if (comboStep > 1)
{
currentStateName = "Attack" + (comboStep - 1);
}
string attackStateName = "Attack" + comboStep;
Debug.Log("Triggering attack animation: " + attackStateName);
if (HasState(attackStateName)) {
// Remove existing transitions from the current state
RemoveAllTransitions(currentStateName);
Debug.Log("Removing Trasnisitons from " + currentStateName);
// Create a new transition
CreateTransition(currentStateName, attackStateName, "Attack" + comboStep);
Debug.Log("Created Transition from " + currentStateName + " to " + attackStateName);
// Set the trigger for the next attack
playerAnimator.SetTrigger("Attack" + comboStep); // Use triggers to transition between attacks
Debug.Log("Attack" + comboStep);
Debug.Log("Set Trigger for " + "Attack" + comboStep);
}
else {
Debug.LogError("Animator state not found: " + attackStateName);
}
}```
They're performed in this function below, and when TriggerAttackAnimation is called is called on top, the animator methods work, but when called below, they fail to function. I've worked on this for hours, debugged 50 different ways, all of my variables are named correctly, there aren't any syntax errors that the compiler or IDE are finding in my scripts, the animator methods are the only things not working
```c#
public void PerformComboAttack() {
AnimatorStateInfo currentState = playerAnimator.GetCurrentAnimatorStateInfo(0);
TriggerAttackAnimation();
if (!currentState.IsTag("Attack"))
{
isAttacking = true;
comboStep = 1;
//TriggerAttackAnimation();
comboTimer = 0f;
}
else if (currentState.normalizedTime >= 0.9f) // Ensures the current animation is almost complete
{
comboStep = Mathf.Clamp(comboStep + 1, 1, 3); // Adjust the max value based on the number of combo steps
//TriggerAttackAnimation();
comboTimer = 0f;
}
}```
anyone have any good tutorials on procedual generation for 2d platformer , with different room sizes?
Use #๐ปโunity-talk for general questions as this is a coding channel. Also don't cross post please.
Probably clarify what's not executing, the code or the animation itself.
A few ideas on how to debug this stuff is to use visual studio's debugger and step through the code, and you can watch the animator in the editor window when it's currently executing and playing those animations.
Is there a way to check what the main thread is stuck on? Seems to be an infinite loop that increases memory and I'm pretty sure I haven't touched anything since last run...
Run the game with the debugger attached. When you get into the loop (when the game freezes), go back to the debugger and hit the "Break All" button to see where the execution currently is
pops up with source not available
nevermind, I've found the culprit
logging is mega expensive
Please do not post the same question in multiple channels, stick to a single one instead
Don't crosspost
Why does terrainData.GetHeight() always return 0 despite the terrain having different heights?
I'm looping through every pixel in my heightmap and trying to grab the height from the terrain
It shouldnt. Mind sharing your code?
Probably because the coordinates your passing in are in the wrong space
Iirc it's 0..1
The input coordinates are integers so I think they are heightmap coordinates
Although docs dont really specify it
Oh I must be thinking of some other api then
for (int y = 0; y < HeightMap.height; y += jump)
{
for (int x = 0; x < HeightMap.width; x += jump)
{
var pixel = HeightMap.GetPixel(x, y).r;
var normal = new Vector3(x, _terrain.terrainData.GetHeight(x, y), y);
if (Vector3.Dot(normal, new Vector3(x + jump, _terrain.terrainData.GetHeight(x, y), y + jump)) < 1f)
{
var tree = Instantiate(_treePrefab, new Vector3(x, _terrain.terrainData.GetHeight(x, y), y), Quaternion.identity, transform);
//var data = tree.GetComponent<Tree>().data as TreeEditor.TreeData;
//data.root.seed = UnityEngine.Random.Range(1234, 9999);
//data.root.UpdateSeed();
}
}
}
going through debugger; x and y increase as expected but every getheight call returns 0
*dw I will sort out the efficiency and naming once it actually works ๐
OnEnable for ScriptableObjects doesn't seem to be reliably executing, either in play mode in editor or in a built player
Is there something special about it that might cause it to not execute?
I've got 8 instances of an SO with a Debug.Log in their OnEnable, but sometimes only 1 executes, and other times it might be just 4 or 6
It should be run when the object is loaded, though is there something you need to actually do in OnEnable? This would imply your SO has some mutable data associated with it
Yes, a static list storing all other instances for ease of access.
Though looks like OnEnable isn't reliably called unless a reference to it exists in the scene, so going to have to go with a singleton carrying a list of them
how do you create those instances?
That's correct behaviour for SO's
If they aren't loaded (not in scene) they don't get enabled
one trick you can use instead of that is to add it to the "preloaded assets" in the player settings, which will make sure it gets loaded immediately when the player starts... you just have to be aware it behaves slightly differently in editor, it only initializes once, not every time you hit play
oh shoot, I never knew about that
great
Looking for ideas.
I have a product that I'd like to be able to do customer support for by allowing users to enter a simple-ish coupon code. I'd like the codes to be one-use-only and tied to a user ID (I'm currently using a nano id - 13 digits and reasonably easy to type: https://github.com/codeyu/nanoid-net using Nanoid.Alphabets.NoLookAlikesSafe).
My rewards are all codified in an enum, so I'm envisioning a tool that could generate a short string. Ie:
UserId: abcdefghijkl + List<RewardType> = coupon code string
where the coupon code string could get the list:
public static List<RewardType> GetReward(string userId, string couponCode) { .. ? ... }
Any thoughts? Ideally the coupon code is easily typed.
I suppose I could also sacrifice the List of enums and just use a single value, since that's likely to generate a coupon code that's denser/shorter
ie, if I tell a user "hey, enter a89m408nmav08vm4a9038gn9as834hj98jadfkasjef90w8jh90834jjoijasodfign as your coupon" they're not gonna be thrilled
(I can handle one-time-use abuse, but there's no way to really make it 100% bulletproof if someone can figure out the algorithm and put it on the internet, though, so maybe a little bit of security through obscurity is OK here)
or maybe there is..? ie, userid + secret admin key + reward = coupon; coupon + public key + userid = reward?
You don't have a server that can handle this?
no server architecture whatsoever
Also, I don't understand what customer support has to do with coupons and rewards.
I'm a bit confused - the idea here is like... you want to give a user 20 points, so you say "Hey your coupon code is {userid-20points}" and it should work?
so, it's a mobile game.. imagine a guy emails in and is like "the game crashed you suck" and we can say "oops, you're right, here's a coupon ABCDEF for 100 gems" or whatever, guy is happy
Something along those lines?
Is there anything that stops him from just reusing the same code over and over again?
ya, something like that, but ideally something that he doesn't go "hey internet, enter this coupon {PraetorBlue-20points} and you'll get free points lulz"
I'm not sure how this can work without some kind of centralized database or server
how would you stop multiple redemption
I can handle that on the game client, ie, add the coupon to a hashset of used coupons or whatever
I guess with the idea that if they're savvy enough to modify their local save data they can just add the gems anyway?
Perhaps, but I'm less worried about that since it's stored as binary
What if you do want to give them 100 gems more than once?
I mean, that's possible too obviously, but less likely to be "easy"
oh, good call.. hm
Wouldn't that just be another code?
Probably would have to .. I dunno.. do something date related? Open to ideas
yeah you could encode a timestamp/expiration data into the code too haha
it's getting real dicey though ๐
well currently I have this existing "RewardType" enum that would be easy to use and I was hoping to use that, since there's a pretty wide variety of "reward" use cases
right? i thought it would be a trivial problem to solve but the more I think about it the more I am.. stumped
How do you get their user ID anyway? And what is the user ID if there is no server?
like realistically you could do this with JWTs. The game client can know how to decipher/authenticate the JWT and only you have the private key to sign a JWT.
But that won't give you a pretty code, it would be a base64 ugly thing
public key cryptography
Basically the requirements are something like:
- Take a 13 digit userid string
- Generate a coupon string from #1 that codifies a list of
RewardType(enums) - Make it "hard" for users to generate this on their own, or share the coupon.
Nice little example on the front page here
https://jwt.io/
Yeah.. I don't know if a user is gonna be able to type a base64 string..
You could always hash it
it looks like I might need to setup some lightweight webapi and have the game be able to call it or something
shame, because it would be a pretty ideal solution for the rest of your requirements
I'm not opposed to it.. or maybe the lightweight web api just puts the base64 encoded value online for a couple days or whatever
ie, "thanks for your email PB, your coupon code is 12345", you go to the app, type in your code, it goes to http://sharping/coupons/12345/pb-user-id-abcdef/ and that returns json of the base64 string, which the game parses and grants you the reward for (once)
yep that could work
still requires setting up the web service but... is pretty foolproof
coupon could come down a few days later or whatever (or maybe even immediately after the user hits it once)
or never, perhaps, if i wanted to do some promo or whatever
nanoid generated on player creation
visible to player in game
Since you can write data like a unique key and the user id into the JWT, and can just have the client not redeem that unique key more than once, you wouldn't need to worry too much about it staying up and getting "reused".
As long as you make sure your client checks the user id and the unique id of the coupon against its internal stores
Just thinking out loud, maybe isn't possible, but what if you XOR the user ID with the coupon payload? The game reverses the XOR, verifies the payload is in the correct format, maybe with some magic bits it expects in certain places.
The length of the code would be dependent on how small you can make the coupon payload.
right, i could do that, but some genius will figure it out and then publicize the coupon, i'm sure
ie, make some webpage "cheats for sharping's game" with coupons users could generate just by typing in their userid
i mean, maybe it's unlikely, but.. i'd like to at least make it a little harder than trivial to break my game
fundamentally this is my problem ๐
So you don't need any additional data except the RewardType enum?
yeah there's basically two ways to do that - encoding the data directly in the coupon string, or having it be a key into some external thing like your lightweight web service and getting all the details from there
Which we've discussed here
the benefit of the JWT is that only you will be able to generate them. And you can easily validate if they're authentic
i'd prefer to not do the webservice if possible.. mostly just in terms of cost and tech.. game is just about ready to launch, i'd hate to have to spin up another service
If someone tries to make one of their own, they will not have your key and your client can reject it
game costs 0 to run currently (ie, no servers, databases, etc).. we'll eventually do teams and multiplayer and all that nonsense but i was hoping not to for now
this is fair
Honestly it would be pretty janky but you could host the JWTs in a public github repo and that would be free.
just commit new coupon codes to the repo ๐
lol
with the coupon code as the filename
i mean, if i have to spin up a web service to host the jwts, that's.. probably fine..
just trying to dream up something that hits all the requirements without incurring too much cost (ideally $0)
How many players are you expecting initially? If I was making a live-service or mobile game, I'd be looking at using PlayFab, which is free for up to 100K players.
I might honestly just do the XOR style approach
KISS
yeah playfab is too much infrastructure for this problem
(I also have partners who hate that company with a passion)
Honestly anyone smart enough to reverse engineer a thing like that is smart enough to modify their gem count in your binary data anyway
perhaps - the binary data is pretty resistant to that sort of thing though
does it have a checksum?
like I've cracked it open myself and it's ... really obscure, even knowing the exact structure
I see
i'm using messagepack
I think most cheaters on Android are using Cheat Engine like software to change stuff in memory.
I don't think it has a checksum .. you can occasionally see string data but primitives are really hard to find/see
yeah, i can't do much about that, and that's fine tbh
Doesn't something like https://ref45638.github.io/msgpack-converter/ just pretty quickly crack that open?
MsgPack Converter helps Decode and Encode between MsgPack(base64 or []byte) and JSON. It is an easy and simple use online tool to convert your data.
yeah this too
i dunno! lemme try
Cheat Engine would bypass the save file entirely
I didn't know if it existed on Android though - but I wouldn't be surprised if it does, or another similar tool by a different name.
I don't think this can parse byte[]
but I'm having trouble getting it into the tool from a text editor
vs code fails utterly at rendering byte[] in any meaningful way
you'd have to base64 encode it first
i don't really understand what their web form means by uint8 array going into a text field lol
hm.. I think it would be pretty hard to reverse engineer this - it's packed using a custom uh.. format? ie, there's no delimiters or anything
if you're on a unix system you just do cat myfile | base64
lemme see if I can do something simliar with windows, maybe in powershell or something
Encode file to Base64 online and embed it into any text document such as HTML, JSON, or XML
i'm sure you can in powershell but maybe not without installing some extra thing. no idea
3AAbB84AAwxyjMQQZtYdAF+Ss0SbyicSJNzJdAPEEH35aTdHeuBOutUIGZ+IjH8DxBAW9HtvFRYnRbP5Z1DmnLA3A8QQoq9fn0Ouj0W6oo5Wv9+wKgPEEIgs/S92dNJMvRr3af0inXcAxBAFKQdwzW36Roz4Yu8fFX3JAMQQfm5UO3YwAUORq1mKoKlw/ADEEB1j5/1tuhdNgZSNMHSTGKwAxBC8TZWYxHRkRpTnKuFfiOjUAMQQr7X/IgQKiEGsBBk+B0DcLADEEHquS/8mNTlCgIHKKpVXFhoAxBDpvXOnDWH6Sodb8cG0JFMcAKDEED0T4yrHJ39DpAdzBoHO52+RxBBsAmH++7R1R6LXsWklcbOSBM9I3I8HRAAaooQBQgJKAzEESYQBMgIyAzIEMpACz0jcizBMcsLkAgLEEH1qUCGhzQlJib8XsjFDB9TcABTEENCAvKP7sdZPkF3S68C0fS3EEDHHtPH8MUtNojub59HYfqDEEF/etmcRuuRCpldPRomPKHvEEJuSyP+iIkJFsLzox+4bbYzEELpZV9dRjbJIg0xa5HQLUKzEEOflxP/hHmBLjZ0S7uxlrUnEEM/AVNVRQidPrLqd70jvJSzEEA3jt2QwY+9NlVDZiMuba2rEEI3xnhR7DfRNoowcFQssL0HEEAzgnAnhELJEgq8AGhcjap7EEG0Eg5csSY9MibemNDiryi/EEF5SqinBSRFAj9lMrNcifE7EEPVFwAwbACxBjQvc1CHCpM3EEBrJ8kZuXXVGvHe+Qx1Ab9/EEILESSc3WOlItGfFNvKLfmLEEGcP0QN3cnBCtAMbvQkZOOzEEEajSBVVE1NPv1cg/7YfMyXEEAPYhga4KHBHirswz52DDjnEEMzb8ZauSQ9Iiqe9FAOJq2vEEP9lfevKjQxHp/IQb/IWVHiQAYbEEF3cRYAPPPhPodHHFMt36WkBxBBftRiwiRI4R4q2Z0Y/2T7RBMQQyyhRohDeF0SXTV5ZRPl6ognEEMFh7cGrjkxFpWbvKLsmnhYAxBDpeKEvLwPdQ5Tf36FdJA1gAMQQEIoSCkTMEkSn8reWudh9jgAKloEGB5CBBpCBBpCBBgAAoJCVMs9I3I8iFBPMN5OXCAgCxBAQEMncr/1MRo6hiaxKd7bHw2IZlwoKAsQQXsk48ZsmRkqL/6x1z9g2NMMzAJcHBwHEENaLay+mCBhMovi4sjXf5e7DYg8Aw89I3It1idFdxZHEEMsoUaIQ3hdEl01eWUT5eqI=
you can see... some data? but it's not really decipherable
i mean, there's a lot of data points in my save file.. i'm sure someone could tinker and find something useful to hack in millions of coins or boosts or whatever, but honestly i'm not too worried about that
i'm more worried that someone'll figure out XOR or rot13 the reward type with the userid = coupon code
I suppose I could just make it a smidge more obscure .. add some date and other checksum type stuff to the coupon, I dunno
ok I take it back, maybe some data is easy to read ๐
oh well, honestly if you can figure out how to take a random bin file in the depths of the mobile devices' OS, figure out that it's a messagepack formatted byte[], convert it to base64, edit it, then go back all the way to the bin file.. well shit, you deserve a couple extra boosts ๐
it's all security by obscurity
and it will always be that if you store this data canonically on their hardware.
and that's ok
preamble: this is more of an opinion/approach question than going into implementation specifics
How would you go about designing a data oriented, state driven (read: OOP statemachine) character controller? Noticeably going beyond the standard movement options, but extending this towards character unique skills.
Having at this in a more stereotypical datadriven implementation a lot of the transforms would only affect one entity (think character melee attack 1 and 2, where either 1 or 2 have some properties that cannot be generalized in a meaningful way, but are unique to a certain entity, be it player character or boss) most of the advantages (if not all) of walking data linearly are lost, but a lot of complexity is introduced to ensure character state is maintained (be it a marker component in a more ECS-y architecture, or closer ties from Systems to their data, keyvalue tables defining what state a character is inside )
On the other hand, the virtual calls are really not sexy performance wise, as the OOP state implementation would, thinking from the DOP perspective, define what systems run, in arbitrary order.
tl;dr - how to deal with entity unique behaviour in a data oriented programming style without/managaeable bookkeeping overhead
@misty glade You don't have to use JWT either, any public key cryptography will work.
JWT offers a standardized way to do thing that's specifically for the common use cases in web, hence it has all the bells and whistles around it like key ID, algorithm, issuer, etc, which are very unlikely not needed for your case (you can and probably will just hard code your public key and its algorithm in your game anyways)
If you are doing it this way, it will be unavoidable that the coupon will be long and cannot be manually typed, since you need to encode all the information about the coupon into it. I don't think this is an issue though. Is your game PC or mobile? If it's PC, you can just tell your player to copy and paste the code in email; if it's mobile, you can just make it a QR code and let your player scan it.
(And yeah the security is non existent if people really want to cheat and modify your data, just because it's binary doesn't mean people can't figure it out. Reverse engineering is way more sophisticated than "opening files and randomly guess what the bytes mean," it goes way beyond guesswork and much deeper. As always, obfuscation is not security)
Are you doing data oriented or object oriented programming ?
@wintry ember Don't cross-post, please. Pick one channel and remove in all others you've cross-posted.
Hi, this might be a very specific question, if anyone knows where can I ask this tell me please ๐
I am trying to create a runtime terrain generation class, I am using the official terrain tools package from unity, they have a Heightmap class. I am trying to construct a Heightmap from a Texture2D, Texture2D class has a GetRawData() which returns a byte[] with raw texture data, exactly the same that the Heightmap constructor expects. When I try to pass this raw data to the Heightmap contructor, it fails, I am pretty sure that is because of the texture format or something like that, I don't understand texture formats quite well, could anyone point me or give an advice?
Thaanks ๐
( I know this package is not supposed to be used this way )
Maybe explain what exactly you mean by "it fails".
And what api exactly are you using
just because they're both byte[] doesn't mean they're the same thing at all
PNG files and WAV files are both made of bytes, they're not in the same format
correct: this is where the type system can no longer help you (:
Depends on the language, in a language like TS where you can create branded types, eg "even though UserId and PostId are both string, they are different kinds of strings so they can't cross assign to each other (but they can still be used just like regular strings)" then type system can help you to prevent these problems.
(C# probably can do it with upcoming roles and extensions too, haven't looked too deep into it)
But practically speaking, these types of errors are pretty rare and caught very easily, so that's why it's not really a big thing to be able to track on the type level. Even in TS where it is possible, the "UserId vs PostId" scenario is really the only place I've found it to be useful.
I suppose if you are writing code where numbers with units are everywhere, eg some numbers are in meters while others are in miles, numbers with m/s multiplies by numbers in s should give you numbers in m, or some numbers are USD while others are Euro, then branded type could also help.
both, this is more about migration and choosing what approach to take here
I currently have a working solution for my Charactercontroller in an OOP style implementation, but this comes with all the drawbacks of such an approach
MVVM + UniRx + Zenject + NUnit + ZeroMock (maybe)
Do you have a huge amount of enemies at a specific time ? And what is your target hardware ?
Number of entities per scene is still pending, as this is in the very hot path of the application I do not want to waste CPU budget here. low end hardware
I appreciate the meta questions, but would you also consider going into the question I actually did ask?
Well, I am not using any API, terrain-tools package is meant to be used as an editor tool but I would like to use some features of it at runtime so I digged through the code.
(That's why I say it's a super specific question)
Heightmap is the data structure they use internally to store 'noise' data.
I have been investigating and they use some generated shaders to parse from the noise algorithm to a texture. That's really complicated to translate so it can be used at runtime so now I am trying to solve what I mentioned before.
The error I am getting is something like: "The texture width and height must to be equal".
Of course they are equal so I think the problem is the format in which the texture is encoded, I feel that depending on the format the raw data of the texture will be different, I need it as raw as possible.
Thanks for the interest btw ๐
Yea, I know but in the method description that recieves the byte[] it says that the input is the raw data of a texture 2d
Thanks for the interest also ๐
I am asking, because depending on your situation it is a waste of time to go for Data Oriented. You will not gain any performance and will suffer a lost in productivity. I am also asking because I'm not familliar enough with Data Oriented to provide feedback, but I can help with OOP architecture.
I asked you to go into answering my question precisely because I anticipated this response
for not gaining performance..... plain wrong. I did transition other systems from OOP to DOP and gained an easy *20-30 speedup retaining the same algorithms, with optimizations DOP allowed me, the system got a speed up x100, opening up more gameplay options due to gaining budget in the hot path
Sounds like it should work then, can you share the docs for the constructor or method you're using for the heighmap
however, I am not here to discuss those things
but came here to get other peoples insights on their approach of implementing stateful charactercontrollers in an DOP style
I am not saying that you will not gain performance. I'm saying that it might not be worth working to gain those performance for diverse reason. I was just asking you if you wanted information about OOP or about DataOriented. If you want information about DataOriented, I cannot help. But, if you want information about OOP, I can.
my friend. you're wasting both our time dragging this out
I'll repost the question so it does not get burried unnecessarily
How would you go about designing a data oriented, state driven (read: OOP statemachine) character controller? Noticeably going beyond the standard movement options, but extending this towards character unique skills.
Having at this in a more stereotypical datadriven implementation a lot of the transforms would only affect one entity (think character melee attack 1 and 2, where either 1 or 2 have some properties that cannot be generalized in a meaningful way, but are unique to a certain entity, be it player character or boss) most of the advantages (if not all) of walking data linearly are lost, but a lot of complexity is introduced to ensure character state is maintained (be it a marker component in a more ECS-y architecture, or closer ties from Systems to their data, keyvalue tables defining what state a character is inside )
On the other hand, the virtual calls are really not sexy performance wise, as the OOP state implementation would, thinking from the DOP perspective, define what systems run, in arbitrary order.
tl;dr - how to deal with entity unique behaviour in a data oriented programming style without/managaeable bookkeeping overhead
There are no docs, just code, and now you mention, it does not say explicitly in that method what I told you, I just figured it out from other method:
What is exactly a 16-bit raw image file (or 8-bit raw image file) and how can I encode my texture as that?
I can't answer this from experience, I haven't solved this problem outside of OOP. I've heard implementing data oriented state machines is less than ideal, but haven't gone deep into the reasons why that is.
Do you have some further insight into that you can share? It feels like it should be pretty straight forward, or at least not much more complex than an OOP state machine.
I understand that it feels a bit icky to have a whole system and set of components that only gets used by one entity, but in terms of performance, it can't be much worse than MonoBehaviours.
the main problem is inversion of ownership. In an OOP style statemachine the entity owns the system that operates transforms on it's state, by referencing a polymorphic class (accessing the correct V table as a consequence). In DOP the systems own the entities that they perform transforms on. V tables don't exist explicitly, as oprations on an entity is defined by presence (or absence) in their list of owned entities.
Depending how granular the DOP implementation becomes, each function usually associated with an OOP style abstraction/runtime polymorphic function is represented by it's own (set of) systems that own entities to perform transforms on them.
Subsequently, a typical statemachine allowing for onenter, onexit, ontrigger, ontick would be deconstructed into 4 systems, times number of possible states
Hey, I managed to make it work, the problem comes from what I thought, if I create the texture like this Texture2D texture = new Texture2D(size, size, TextureFormat.R8, mipChain: false); it works, I can use TextureFormat.R8 and TextureFormat.R16, now my question is how can I import a texture using this format, I will figure it out,
Thanks for your patience, cheers
i have written some toy examples on DOP and i am less experienced than you, one thing i find out is that once the number of variables to determine the state grows then the cache locality just gone, fall back to OOP
typedef struct{
int x,y,z...;//sizeof(State) is small
}State;//c doesnt have OOP
State states[10000];
type0 otherIrrelvantData0[10000];
type1 otherData1[10000];
then you update it as
states[i]=ChangeState(states[i]);//just copy it
but if your State is
typedef struct{
int variables[100];
}State;
ChangeState(states+i);//pass by pointer
```at least you can still load less data to cache, but (sizeof data needed in ChangeState)/(size of all data of one entity) finally becomes 1 if nearly all data is required to determine the state
What this reminds me of is iterator and async methods in C#. Both are implemented as state machines, just a big switch expression, but are generated from an easier to write and understand syntax. I wonder if you could do something similar with source generators, just like how Unity Entities is using them to simplify many number of things in systems.
If you ignore how the switch expression is created, whether by hand or generated, and just focus on logically and performance-wise, would a big switch expression in one system be enough to solve your problem?
You would lose the ability to dynamically add different types of states that were not known at compile time. Maybe that's a requirement.
it uses bunch of goto (i guess there is no for and while loop and switch case in asm so sharplab show this), probably a handwritten state machine will be better since it is easy to understand for human
the big switch has some other downsides besides source gen (I played around with source gen for my scripting language that I attach to unity for dialogue handling) as all functions in the switch get cached, shooting the cache completely if the switch is sufficiently large, making OOP preferably again to create runtime polymorphism (this is mainly book-knowledge here, I did not test where the tipping point for big switches is yet)
I'll have to give it a thunk
yeah, assembly has no loops, only jumps and labels - loops are just syntactic sugar generating jump addresses and the conditional jumps
the issue is something else, not the state passed into the changestate, but rather what changestate is ran - here all passed in states would experience the same modifications, unless you branch within that function
ofc there are branches inside the function, state machine is a graph and different input travelling on a different paths
if the code is large then instructions cache miss, now a function
pointer becomes a better choices...
but that two both require loading the instructions to cache again and the function one needs additional push stack operation?

the additional push should not matter when there is a memory lookup
I think I'll stick to my current implementation in this case and just factor out the data more cleanly - going with function pointer to branch but keeping data linear in memory for other systems to remain quick
Maybe I'm missing something, but a character controller is only running for one entity right? So I don't think it matters if something runs a few instructions slower or having some cache misses since it's only running once per frame or whatever anyways.
(also entirely random aside, nice to see a black bullet pfp)
I have multiple entities, player, as well as bosses will have unique skills, whereas mobs will appear in groups, sharing behaviour per type. - so it runs once per entity per frame in one way or another
hey, is there a way to investigate what takes shader compilation process so long?
Before I had some shader which could recompile under ~100ms
now they can take even 2/3 seconds
and for my use case I need the compilation to be really fast
(working on an interactive tool for editor)
Trying to figure out a way to add spatial partioning to my grass renderer.
I'm using Graphics.DrawMeshInstancedIndirect and it's a bit slow trying to draw 40000+ grass quads at once. I want to split it into cells that each render a certain amount of grass.
Issue is, I don't really know how to set this up. I've tried looking at github examples (such as https://github.com/ColinLeung-NiloCat/UnityURP-MobileDrawMeshInstancedIndirectExample) but the way I handle everything is different to how they do it so it's somewhat difficult for me to integrate their spatial partitioning method into my own code.
currently I just have a list that contains a struct with houses all of the data for the shader (position, rotation, scale, and some per-instance shader variables). Somehow I need to split this up into discrete cells.
anyone mind helping me with inverse kinematics and procedural animation?
#๐โanimation maybe?
also, don't ask to ask
Well, you could iterate your list and add the data to a separate cell depending on it's position.
Is there any "magic behaviour" for particle system emission module that stops it from playing? I have a PS that's randomly stopping and I can't figure out why (I am setting emission rate over time in a tween but .. that shouldn't impact it?)
I'm seeing my PS isPlaying = true for exactly one frame, then it turns off
(and it's looping.. it should be on)
i'm using Emit() elsewhere
Nevermind, dumb issue. Was setting emission rate elsewhere to the wrong particle system.
Anyone know what this might be? Random error messages in my log:
Unable to perform online search:
Request [GET https://packages.unity.com/-/api/search?host=editor&provider=enterprise] failed with status code [502]
UnityEditor.EditorApplication:Internal_CallUpdateFunctions ()
I got 502 just now while opening a project (installing packages phase) -- looks like Unity's package servers are having issues at the moment
based on discord search, this happens every few weeks
aight, just not really sure what it is and .. you know, we're just about to launch so not thrilled about weird/cryptic errors
got enough regular bugs to worry about ๐
It was back online a sec ago, but now it's broken again.
still failing (not every time, but enough to break project init)
This answer pretty much explains how to get a cell index https://stackoverflow.com/questions/59996236/how-to-calculate-the-cell-a-point-belongs-to-on-an-infinite-grid-plane I would add that index to your data struct. Cull based on the cell bounds in a cpu job that outputs visible cells and then only render based in the matching ids. Of course things can be tremendously sped up by using a more sophisticated acceleration structure such as a octree
I want to get the editor cameras position but it returns Vector3.zero unless I have opened the scene view window at least once before when entering playmode. This is the only solution I've been able to get this far but it looks horrible and I feel like there should be a easier way to do this that I'm just not aware of
[InitializeOnLoad]
public static class Tools
{
static Tools()
{
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
}
static void OnPlayModeStateChanged(PlayModeStateChange state)
{
var sceneView = SceneView.lastActiveSceneView;
if (sceneView && sceneView.camera)
{
switch (state)
{
case PlayModeStateChange.ExitingEditMode:
{
var position = sceneView.camera.transform.position;
EditorPrefs.SetFloat("SpawnFromEditorCameraX", position.x);
EditorPrefs.SetFloat("SpawnFromEditorCameraY", position.y);
EditorPrefs.SetFloat("SpawnFromEditorCameraZ", position.z);
break;
}
case PlayModeStateChange.EnteredPlayMode:
{
var position = Vector3.zero;
position.x = EditorPrefs.GetFloat("SpawnFromEditorCameraX", 0f);
position.y = EditorPrefs.GetFloat("SpawnFromEditorCameraY", 0f);
position.z = EditorPrefs.GetFloat("SpawnFromEditorCameraZ", 0f);
sceneView.camera.transform.position = position;
break;
}
}
}
}
Your unsub/sub on lines 6-7ish don't .. do anything.. unless I'm missing something
I do recall some odd stuff with editor initialize on load.. I tried something a while ago to force it to a certain scene but it didn't work consistently. What are you trying to solve by getting the editor camera position? I'm assuming some sort of custom tooling, but it seems like there's probably a better way to crack that nut
Its a tool to spawn my player from the editor cameras position, and it works but the code is ugly and I feel like there should be a better way to do it
I mean, I might restructure it a bit, but if it works, it works?
I don't understand the unsub/sub in the constructor.. the first line'll do nothing, and the second line will sub (but never unsub, so you'll have a memory leak)
I mean yeah, but having to use EditorPrefs just to store the data between play/edit mode feels hacky
unsubbing from static events before subbing is a good habit to avoid the same listener getting added multiple times if the code gets called multiple times, even though that's unlikely to happen here since it's a static constructor
private const string HackX = "SpawnFromEditorCameraX";
private const string HackY = "SpawnFromEditorCameraY";
private const string HackZ = "SpawnFromEditorCameraZ";
static void OnPlayModeStateChanged(PlayModeStateChange state)
{
SceneView sceneView = SceneView.lastActiveSceneView;
if (!sceneView || !sceneView.camera) return;
if (state == PlayModeStateChange.ExitingEditMode)
{
Vector3 position = sceneView.camera.transform.position;
EditorPrefs.SetFloat(HackX, position.x);
EditorPrefs.SetFloat(HackY, position.y);
EditorPrefs.SetFloat(HackZ, position.z);
}
if (state == PlayModeStateChange.EnteredPlayMode)
{
sceneView.camera.transform.position = new(EditorPrefs.GetFloat(HackX), EditorPrefs.GetFloat(HackY), EditorPrefs.GetFloat(HackZ));
}
}
I'd write it as this, just a bit shorter, but that's just a stylistic thing rather than anything substantive
(keeping the keys in string constants reduces your risk of typo-bugs, which would be hard to find for this)
(i subscribe to the one-indent-club)
quick question for Awaitable , is it needed to "dispose" of these before lets say a scene reload? Or will Unity manage the cancellations when the component is destroyed?
from my research it looks like Awaitable might be a different syntax for the same Coroutines, so maybe Awaitable is managed by the lifetime of the monobehavior?
From what I read, awaitable is just a sum up async method of child async methods. As async methods do not run on another thread, I think there is nothing to dispose.
Their lifetime is not managed and will continue until the end or domain reload
What is hackx are you hacking x.
huh?
I have an ongoing issue on my mobile app that uses firebase. when I run the app in unity, data updates just fine but when I build to iphone the arrays are replaced with empty maps.
Have you tested locally in xcode on that build and watched for any error output in the console when that happens?
You mean with the build to my phone option? That's a good idea. Might take a century on this mac, borrowing it from client and it sucks. takes about an hour or 2. I do have a secret log in the app though so not sure if there is something that would show up in xcode but not the app console?
You could have some silent errors within the SDK that you aren't seeing when its running on the iphone. I mean, its always a good idea to run a dev build within xcode and watch the console if you are having issues.
should also note it's just 2 arrays, there are other arrays not being overwritten. So i have an idea but its been tough narrowing it down. it's just 2 fields of user document that its affecting, everything else is updating as expected
for sure. I usually just build to testflight, client and a few others on there
It may be a code issue then, but i'm taking your word that you said it works in the editor but not on the build. I would build down to android and see if the same thing happens
yep, tested in editor on mac and windows strenuously. I do some weird stuff with the lists so I definitely don't think it's complete voodoo. long story short the user document is a Dictionary<string, object> so to get the Lists I have to do some conversion stuff. Some of that code might work on machine but not phone
{
if (userObject.ContainsKey("CompletedTaskIds"))
{
if (userObject["CompletedTaskIds"] is List<string> completedTaskIds)
{
return completedTaskIds;
}
else if (userObject["CompletedTaskIds"] is List<object> completedTaskIdsObj)
{
return completedTaskIdsObj.Cast<string>().ToList();
}
}
return new List<string>();
}
// Utility method to get UnlockedTasks as a List<string>
public List<string> GetUnlockedTasks()
{
if (userObject.ContainsKey("UnlockedTasks"))
{
if (userObject["UnlockedTasks"] is List<string> unlockedTasks)
{
return unlockedTasks;
}
else if (userObject["UnlockedTasks"] is List<object> unlockedTasksObj)
{
return unlockedTasksObj.Cast<string>().ToList();
}
}
return new List<string>();
}```
essentially it reads as a List<object> but isn't
Might try iterating through the List<object> and add the strings individually into a List<string>
if .Cast is the culprit
yep, tested in editor on mac and windows
Thank you very much!
Please, don't cross-post. Remove this message.
Sorryyyy I didnt know! 
is there any way to run a function before awake but after scene loads?
I tried [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] but it still seems to run after all awakes.
I don't want to use script execution order.
Just the first scene load?
RuntimeInitializeLoadType.BeforeSceneLoad is described as:
Callback invoked when the first scene's objects are loaded into memory but before Awake has been called.
And the docs show an example of how you can access inactive objects in the scene before Awake has been called on them.
awesome this works for me.
weird that it's called before when it executes after load.
thanks
Yeah, agreed. I guess Unity doesn't consider a scene loaded until all the objects have been woken up.
anyone familiar with the terrain's GetSteepness function?
var steepness = _terrain.terrainData.GetSteepness(x / _terrain.terrainData.size.x, y / _terrain.terrainData.size.y);
This doesn't seem to be returning the right values at all
how did you calculate x and y?
it's just a double for loop that cycles through terrain.size
okay, so this isn't a problem with converting a world space position into a terrain-space position
What values are you getting out?
it seems to be working quite decently now, I don't know what I did
just messed around with the values a bunch more
I'm trying to make a collider mask using polygon colliders but when I transfer the points from local to world to local the position seems to be off. I've double checked my points and they look correct.
(The colliders should make an open space where the gap is but the space is below it)
for (int i = 0; i < _maskCollider.points.Length; i++)
{
drillPointsToWorldSpace[i] = transform.TransformPoint(_maskCollider.points[i]);
Transform pos = new GameObject().transform;
pos.position = drillPointsToWorldSpace[i];
drillWorldTransforms[i] = pos;
Destroy(pos.gameObject, 2);
drillPointsToLocalSpace[i] = drillWorldTransforms[i].InverseTransformPoint(collision.transform.position);
}
polygonPipe.points = new Vector2[]
{
new Vector2(_pipeCollider.points[1].x, drillPointsToLocalSpace[2].y), // Top Left
new Vector2(_pipeCollider.points[1].x, _pipeCollider.points[1].y), // Bottom Left
new Vector2(_pipeCollider.points[2].x, _pipeCollider.points[2].y), // Bottom Right
new Vector2(_pipeCollider.points[2].x, drillPointsToLocalSpace[3].y) // Top Right
};
_pipeCollider.points = new Vector2[]
{
new Vector2(_pipeCollider.points[0].x, _pipeCollider.points[0].y), // Top Left
new Vector2(_pipeCollider.points[0].x, drillPointsToLocalSpace[1].y), // Bottom Left
new Vector2(_pipeCollider.points[3].x, drillPointsToLocalSpace[0].y), // Bottom Right
new Vector2(_pipeCollider.points[3].x, _pipeCollider.points[3].y) // Top Right
};
where this can be used. any examples you got.
And the docs show an example of how you can access inactive objects in the scene before Awake has been called on them.
consult the documentation
so its just accesing inactive objects in the scene when the scene loads thats it fen.
more generally, it can be used to run code as the game starts
I use it to load some singletons with Resources.Load
you mean entire game or the single scene which is active you can run that code.
The entire game.
I'm not sure how you'd run code after a scene is loaded but before Awake gets called on anything
i never used that but the scenes which are not in use. can i access them also with that code.
are you sure about the entire game with plenty of scenes or just the active scene in use fen. which will get affected by this code RuntimeInitializeLoadType.
I'm having problems with SerializationUtility.HasManagedReferencesWithMissingTypes.
I have a prefab with a MonoBehaviour attached to it that has a missing managed reference. The inspector warns me about this, and I got a warning when I originally broke the reference (by changing the namespace of a class).
However, HasManagedReferencesWithMissingTypes is returning false. I checked that my editor code is, indeed, passing this MonoBehaviour to the method.
foreach (var entity in entities)
{
foreach (var component in entity.GetComponentsInChildren<MonoBehaviour>())
{
Debug.Log(component);
if (SerializationUtility.HasManagedReferencesWithMissingTypes(component))
{
Debug.LogWarning($"{entity.name}'s {component} has broken managed references:", component);
}
}
}
The Entity component gets logged here, but no warning is printed
yes probably you save it and access it.
however, I don't see a way to get a list of the broken references: PrefabUtility.GetManagedReferencesWithMissingTypes doesn't exist, and SerializationUtility.GetManagedReferencesWithMissingTypes can't find anything
this is more of an #โ๏ธโeditor-extensions problems so i'm going to move over there
is there something to do with SerializeReference
i dont use much editor stuff.
what i am thinking about this RuntimeInitializeLoadType.BeforeSceneLoad is the scene is loaded in the backend and this code runs. its like the scene is there already and its visible after running this RuntimeInitializeLoadType.BeforeSceneLoad. or the scene is not there and this code RuntimeInitializeLoadType.BeforeSceneLoad executes.
seen the documentatiopn but got confused with the above.
any profesional graphics programmers here?
just wanted to ask how to create a circilum to study graphics programming.
Start by learning to spell ?
Start by making your own engine. By doing so, you will understand the base.
Okay, so I have a chain of nodes which consist of a Vector3 position and a Quaternion rotation. The nodes always have a consistent equal spacing between them.
I have a method that takes a list of nodes, a to and from index of the nodes to modify, and a Quaternion offsetRotation.
What it does is change the position and rotation of each node in the specified index range. So that the to node ends up being rotated by offsetRotation
The way this is implemented right now is 2 nested for loops. The inner one adds a incremental rotation to each node from i to chain.Length, while the outer just loops from from to to.
(https://gdl.space/wuficunimu.cs)
The attached image illustrates what I mean about how iteratively moves the nodes up the change from i (the green ring)
This ends up being pretty slow as I have a lot of nodes and a lot of chains. Particularly the Maths.Mul as it is 2 Cross calls.
I assume there is a lot better way to do this, I am just not sure what it would be atm. Any advice?
Not a full answer yet, but if the nodes always have equal space between them, why does each node have a Vector3 position? Wouldn't it be enough just to have the rotations and one root position?
I guess, but I evalaute points along the chain of nodes like one would with a spline. So I would have to compute all of the positions of all of the nodes up the whatever t point is being evalauted.
So basically just caching it I guess.
The chain can be in any arbitrary configuration when you do this, right?
Not just straight
Yeah, exactly
It's a bit hard to imagine what the end result should be if you start with, for example, a chain in a S curve.
What if the last node just happens to already be rotated the correct orientation? What happens to the other nodes?
It is an additive rotation from the from node. So if you say rotate 45, And the to node already has a rotation of 45, it will end up with a rotation of 90
Oh okay, that makes sense.
If the data structure was all relative instead of world space, that would speed up this particular computation. But makes sampling afterwards slower.
Maybe it makes more sense to have the data in relative form, and also without the position, and then precompute a world space cached version of it after modifications have been made.
Hmm, maybe so, that feels like it would be faster as it would get rid of the double nested for loop
Or... would that work...?
This particular modification is even parallelize-able at the node level, because each node would be modified by the same amount, with no dependency on their parent node.
So each relative-space node would just be a rotation with the root node having a position. Right?
Yes.
Hmm, yeah I guess so, cause then you would keep a cumulative rotation, and basically apply position + fixed distance *cumulative rotation at each node.
Sorry, just trying to wrap my head around it and make sure it makes sense because it is basically the 'opposite' of how it works now as the rotation is actually just calculated from the positions of the previous and next nodes.
And yeah I could parallelize this rotation operation you're right. It was annoying that I couldn't since it is basically just doing the same thing to each node haha.
Thanks @sage radish this seems like a good choice. And if I need to for some reason. I can still write methods that act on the world-space version.
Also, don't forget about Burst. It looks like you might even be able to just add [BurstCompile] to that static method (and its parent class, so Burst can find it). That alone might give you a nice speed boost. Looks like all the parameters are Burst compatible.
I always forget I can use Burst on static methods outside of Jobs.
Yeah, definitely do that.
Haha I also forget all the time you can burst static stuff. But didn't do that since the implementation felt like it had issues, and just slapping burst on it felt like just covering up 'bad' code instead of actually fixing it.
I got a huge speedup on noise.snoise calls by doing that
Yeah same haha. Its great. I just prefer to actually optimize my code properly before bursting it.
This doesn't have anything to do with code. #โฐ๏ธโterrain-3d would be the appropriate channel. You can copy your message in to that channel, and then delete it from here to avoid double posting.
it's kinda related
since i'm currently doing some weird runtime terrain generation
but alr
sorry for wrong channel my discord said it was #archived-shaders
I've created a basic chain of responsibility system to use in my game. Idea is to use it for input handling so input can be taken away from the player at any time easily https://gist.github.com/BradFitz66/69948fddc098ab6f88854443ffd71943
How does the code look?
A more complicated example could include multiple 'chains' linked together. You have the InputHandler which populates the data with the data from player input, and then something like a CutsceneHandler which overrides the data in InputHandler before whatever is requesting the data gets it.
small error in ChainManager.cs inside the loop in the GetState function. data should be set to the return value of chain.Value.Execute(data)
Hello everyone! having this weird issue where raycasting only works when moving the target in x or z
for context:
the object selected that has the gizmos is the enemy, this moves towards the player using:
public bool CheckView(Transform target) {
return CheckView(target, maskObs);
}
public bool CheckView(Transform target, LayerMask mask) {
Vector3 dirToTarget = target.position - Origin;
return !Physics.Raycast(Origin, dirToTarget, dirToTarget.magnitude, mask);
}
heres a bit more code regarding the enemy controller https://paste.md-5.net/idofawigol.cs
and it only triggers when moving fast enough, even without rotation
looks like CheckAngle is wrong
i took CheckAngle from an older version of this project, weirdly enough i also took CheckView.
this video is using
private bool TargetInRange() {
return _los.CheckRange(target) && /*_los.CheckAngle(target) &&*/ _los.CheckView(target);
}
maybe this says something to you?
printed TargetInRange in the update and its indeed an issue with that method and not the nodes / trees
- what is Origin and where is it set?
- what is the raycast hitting? Debug.DrawLine to see where it's casting
- have you stripped out this fsm stuff to focus on the problem?
1- Origin is transform.position, heres the full class sorry https://paste.md-5.net/quqefufume.cpp
2- ill give it a try
Also your raycast in CheckView is very suspicious
public bool CheckView(Transform target, LayerMask mask) {
Vector3 dirToTarget = target.position - Origin;
bool isClear = !Physics.Raycast(Origin, dirToTarget, dirToTarget.magnitude, mask);
Debug.DrawLine(Origin, target.position, isClear ? Color.green : Color.red);
return isClear;
}
its honestly so weird
is there some better way of doing this? its what my dumb ass useless teacher gave us
not weird, if you print what's being hit it's probably the player's collider. That's why the raycast is weird, you're checking if anything is in the way between the player and the other thing but you cast a ray that will detect one or the other 100% of the time
that's probably why it works if you move the collider really fast before the next physics update, but are running the TargetInRange in an Update loop
if you're doing a los check, you either need to filter that out or put those colliders on a different layer than the one you're using to check for collisions
you are right! it is the capsule collider
changing the layer seems to be working, thanks!! i have been smashing my head against the keyboard for like 3 hours with this 
i understood this what happens in the backend. i would say help yourself.
do u guys know how nav mesh pathfinding calculate the path after using A* for choosing rectangles ?
heya, is anyone aware of the best way to place points on a mesh uniformly (not necessarily randomly) in a compute shader?
i'm having some trouble
I'm aware of poisson disk, but in this case, there's no example of how to use that in 3D + also in compute shaders, so I've had trouble figuring it out. my current methodology is to generate X points per triangle, then in the compute shader, place them on the surface of that triangle uniformly
the issue is the "uniformly" bit as you can see
it can get somewhat close but there are some obvious artifacts around the edges of triangles
nevermind, fixed it
was assuming the id of the given compute shader thread was at the start of a triangle so it was connecting all kinds of incorrect things
Need help with ImageEncoding on Job.
The logs print correctly but the saved result isnt encoded.
When I dont use jobs it works fine but doesnt when used with it.
Any idea what Im missing ?
does unity warn you memory leak?
nup, everything is taken care of
The logs,
Notice that upon job completion, the array is 22353 but when read from coroutine its back to 2.5 mb
Im missing something obvious at this point but unable to figure out what
you are assigning a new native array to your job instance storage (and without dispose it the one not be disposed is resultBuff, so i wonder has unity warned you there is memory leak) but not using your own allocated buffer
no there are no such messages
Not a code question. Please use the correct channel #๐ฒโui-ux
But... Instead of using 2 Canvas's why not use 2 panels in one canvas?
how to check how close some point is to the object's bounding box
like Vector3.distance(SomePosition, RaycastHit.hitPoint)
but without a ray since there is no collider
you could use Renderer.bounds.center
well, i need to get how close the object is to one of the bounds(to the nearest bound), not to center
basically i want to change pixel error on a terrain object as player approaches it
so if player is, for example, 128 units away from the bound of terrain, pixelError should be around 50
once you have the distance to the center you can use the rest of the bounds variables to calculate the distance you want
well, how?)
currently my terrain is 2048x2048
and player can approach from anywhere
it's simple math. Look at the bounds docs and see what properties it has
now, don't you wish you had looked at the docs first?
I didn't know i can get bound from terraindata
thought it's a different thing since there is no mesh renderer
so i thought there is gonna be nothing in the docs, that's why i went here xD
ANYTHING which is going to showup on the gameview must have some kind of Renderer. bounds is a property of that
well, terrain doesn't have renderer
not even sure that my data solution is gonna work now
and yeah, it didnt
TerrainData has a bounds property
yeah but it's counting like terraindata is on 0,0,0
so i wrote the method which fixes that
is loading images from Resources faster than from the file system?
They're two completely different concepts
When you load an asset from Resources, you're reading data that was imported by the editor and stored as part of your game's asset files -- it's a Unity object, like Material or Texture2D
Reading a file just gives you text or bytes.
So if you load an image from the filesystem (say, from StreamingAssets, or from the user's Download folder), you need to do something to turn that image data into a texture
fastest is to put the images in a field through the inspector
For the camera component, i want a render type that is not orthographic nor perspective. I have a function to determine the screen-space coordinates of a 3d vertex. How would modify the render pipeline to implement this if at all possible?
You can create custom projection matrices and assign them to a camera. However, GPUs only support linear projections, due to how they interpolate between vertices. So, you can't create a spherical or cylindrical projection, for example.
If your function is linear, but can't be encoded as a matrix, you will have to write a custom shader to perform the projection. Everything in the scene will have to have a custom shader.
If your projection is non-linear, you have no option but to bypass the GPU's triangle based rasterizer completely, and write your own raytracer.
I am praying that it is linear and will look into custom projection matrices. thank you
Hello, I am learning Netcode for Entities and can't get how to rebake object to new world.
On start I have defaultWorld where everything is baked, after user connected to server I am creating 2 new worlds, client and server (it's through relay so acting like a host).
And in the default wolrd I have my enetity which I need but it's not getting baked in the 2 new world. All of them have same subscenes etc. How do I make authoring component to rebake in new worlds?
Thanks
In the profiler, if a function is shown as a child of another, does that mean that it was called directly from it?
The image shows an example. The function SceneSettings.Update(), there are 3 functions below it: Loading.ReadObject, Mono.JIT, Instantiate, but I don't think they are directly called from the Update?
They can be indirectly called.
They also might not appear anywhere in your code at all
notably, Mono.JIT is counting time spent doing just-in-time compilation
Profiling works by measuring how much time you spend between the start and end of a marker
By default, there are not very many markers.
Deep Profile slaps a pair of markers onto every function
Without that enabled, you can have many layers of function calls between a parent and one of its child markers
ok
so by default the profiler puts Profiler.BeginSample("Mono.JIT") at the start of the mono.JIT, etc?
Something like that
I'm not sure that one is even a "function", per se
it's just marking time spent by the runtime on JIT-ing
got it
Hey everyone! For context, I'm working on an RTS game and need to store arbitrary collections of units. I'm trying to plan a class to hold onto a list of objects, called a UnitSet. This class should function as a wrapper for a collection and provide methods to read, write and modify the contents of the collection as speedily as possible. I'm wondering if anyone has some general thoughts that might be able to help - I haven't entirely yet decided whether the underlying collection should be an array, a hashtable, etc.
My requirements are:
- High memory cost is allowed, memory paging is desirable.
- Does not need to be contiguous, so null entries are okay at times.
- Must be able to very quickly determine if an object is already in the collection (as a hashtable would), as Add(Collection) and Remove(Collection) need to act on intersecting conditions, throwing out cases where an object is already in the collection or not, as appropriate.
- Must be able to sort frequently according to unit's selection priority (so that important units appear earlier in the collection on demand).
This class would be used pretty generically, but would be the parent to such things as control groups, so it needs to stand up to very fast changes. Also, as units die, the class would have to remove elements one-by-one through events. I'd rather not rely on Unity's null implementation at all, as units will be not be destroyed when killed per se, as part of my own batching system as well as for gameplay reasons.
I figure that the best way to achieve this is to make the UnitSet class keep track of multiple different "views" of the data, such as a dictionary to count how many of each unit type is in the collection so as to make this kind of information available without reorganizing the underlying data as often as possible.
EDIT: Whatever I do is probably going to use a lot of Span<T> for actual manipulation.
I think I would have something like this
List<UnitSet>
Dictionary<int id, int ix> where id is the unique id of the UnitySet and ix is the index into the List
SortedList<object key, int ix> where key the the variable from UnitSet to sort on and ix is the index into the List
or implement your own sort and instead of the Sorted List just a List<int> or int[] where that is the ix of the original List
Good thoughts - I am also considering a round-robin garbage collection routine to clean up old UnitSets. The actual unit class is BaseUnit, fyi. Thanks!
I'm a bit unsure whether Lists are useful at all in this case. I know I want the main collection to have a fixed size, currently thinking 512. For that reason, I think Lists are out and arrays are the only real way forward. I'm honestly caught on figuring out if and how the managed collections are optimized in the "right" way to suit my needs, and I'm leaning on thinking that they aren't, besides the default array, of course.
that would be simple. Set them to null in the list and remove the entry from the dictionary
In the case of a unit dying - yes, exactly my thoughts.
if you have a fixed size then, yes of course use a UnitSet[] instead of a List, much better
you can maintain a separate count as to how many entries are in use
My biggest concern, I think, is ordering and being able to determine whether an element exists in the collection. In the latter case, this is why I had considered a hashtable at all, but using the object as it's key may work, as well. I can also assign unique ids in the form of integers for units - even if they don't actually get destroyed and are instead resurrected for pooling, that id would change.
Probably, I don't need the objects in order in the array; just having the dictionary sorted would be alright.
not a good plan and you mentioned needing to sort frequently which is why I would have a separate sort structure indexed into the original array/list
As long as the class can spit out a sorted list, the data doesn't actually have to be sorted in memory, is what I mean. UI components will need to be able to populate with high priority units ahead of lower priority ones.
Here is a visual example of why this careful control over the unit set class is important:
https://youtu.be/bexWuHmV32A?t=91
It's somewhat a complex problem imo, and I really want to thank you for your insight @upbeat path.
An "over the shoulder" APM video of GSTL All-Killer StarTale_Sound! The video shows his monitor, keyboard and mouse while playing at the WCS Challenger League Qualifier!
I could also do things such as flag within the class whether the data is known to be contiguous, or if there could be a delay in spitting out neat data (dirty). It's a pretty benchmark component to the game that I'm making.
tbh, Its not complex at all, it's just a question of good data design. but at least you are asking the right questions
Yeah, I substituted "complex" with critical lol.
These unit sets will also be networked so that each player in a game will have a synchronized knowledge of all UnitSets. This is both for helping synchronize AI behaviour as well as letting players show each other what units they're controlling, etc. Not all data needs to be real-time, but some should be.
how many different variables are you going to be sorting on?
Basically just selection priority, for UI stuff. Selection priority would imply that units of the same kind are also ordered, so that's probably it.
in that case I would not use any of the sorted collections and just maintain my own sorted array of indexes as things change, that can be implemented very efficiently and much faster than any collection
Well, if you have a public API surface designed, then you can always just use the most basic implementation first, and do a profiling to see what your actual access pattern is. Perhaps in practice it's doing less sorting than you think so that can be deprioritized, or perhaps it's the opposite and you have to prioritize sorting over everything else. It's much easier to make judgment calls with real world data, then you can just swap out the implementation without needing to change any consumer code since your public API surface is already fixed (or perhaps with these additional insight you can redesign your public API to work better with the underlying implementation)
Yeah, this is already a rewrite of a system that I scrapped, having learned that some degree of self-management is needed in C# to achieve what I want. I'm on the ground level of really working that out, but suffice to say that I already learned that the built-in classes aren't enough.
This discussion was good, nonetheless - you've largely mirrored my own thoughts. And yes, testing will be necessary throughout.
Have you profiled it prior to ripping everything away? Ideally you should have some concrete numbers on your access pattern to aid your decision making.
what is your target platform?
Honestly, it was simple and relied a lot on Linq for monad-like utility. It was bad no matter how you slice it.
PC with HDRP.
Good for prototyping gameplay, but nothing near a proper implementation.
You don't need the absolute numbers, but more the relatives, eg I have 3x as many reads as inserts, and 1.5x times as many inserts as deletions, etc.
That will help you know which access you need to prioritize.
Ok, I made a similar system some time ago and passed off all this kind of work to separate Threads so as not to impact the main thread. you might like to consider that although with only 512 units it should not be necessary, I was dealing with 5,000+ units
Maybe, yeah. As long as the work is less than the time it takes for a frame to render, this is probably the best approach.
in real terms it does not matter if the data is not 100% accurate frame to frame as long as it syncs within a sensible amount of real time
Yeah, exactly. I like the idea of marking whether the UnitSets are known to be clean or dirty. Many of these classes will update many times per second, but not all.
Thanks a ton! I think I have plenty of ideas to work with.
Even better, then you can have different threads running at different priorities, the foreground dirty Units go into the high priority thread and the background units go into the lower priority thread(s)
but now we are talkng about serious optimization, I very much doubt you will need to go that far
More likely, whatever directly affects the local player is high-priority - especially if they paged certain control groups before others. Scenario-related sets or anything that gets produced as a result of an AI eyeing the battlefield can be low priority - I want to make sure that the player's control is unhindered. Whether a unit is in view or not actually doesn't matter as it is essentially foregrounded if it's referenced in a group that is high priority at all.
Souinds to me like you are on the exact right path, best of luck with your implementation
Thanks! Time to white-board.
lol, RTS games are fun to design and build but, damn, they do make you think rather more than you want to
It's got to feel good to be good, bud.
Abso-bloodly-lutely
there is no better feeling than when a plan comes together and it 'just works'
heya, anyone experienced with compute shaders that could help me out?
I've written a compute shader that takes the vertices & triangle indexes of a given mesh. the shader's x thread id corresponds to the triangle # (in this case, there's only 1), then the y and z ids are used to place them on the triangle
I'm getting really strange results though. f.ex, with only three vertices, even though they log as (1.5,1.5), (1.5,0.0), and (-1.5,1.5), occasionally the (1.5,1.5) vertex will appear in the shader to be positioned at (-1.5,-1.5) instead. just weird stuff like that- if I reenable the component (and restart the shader), it will then appear normal again
I'm pretty new to using compute shaders so I'm sure I'm doing something wrong here
hi guys
i have a value which i want to operate with each frame
int val = 5; // goes from 5 to 100
int thing = 1000; // goes from 850 to 1700
int botBound = 850;
int topBound = 1700;
val = some kind of lerp(850, 1700, 5, 100);
i want the value to be 100 when thing is 1700
and 5 when thing is 850
if lower than 850, then it's still 5, if higher than topBound, then it's still 100
is this really advanced ๐ sounds like a simple clamp and remap
This might be because of the number of dispatches * numthreads. The number of threads invoked will always be multiplies of the numthreads you've assigned. So if your numthreads is set to (8, 8, 8), then the minimum number of threads you can dispatch is 8 (if you don't count 0).
For this reason, you may need to check to see if the uint3 id you get is outside of the range you want.
isn't that some kind of task which Lerp can handle
in a single line of code
(i don't know how lerp works cuz never used it)
ahh, alright, that makes sense. any number above one for the formula I'm using to sample a position on the triangle will screw with it so that's almost definitely the issue
[numthreads(8, 8, 1)]
void InitializeGrassChunk(uint3 id : SV_DispatchThreadID)
{
GrassData grass;
int adjId = id.x * 3;
float offset = id.x % _GrassPerTriangle;
float3 v1Pos = _PlacementVertexBuffer[_PlacementTriangleBuffer[adjId + 0]] * _Scale;
float3 v2Pos = _PlacementVertexBuffer[_PlacementTriangleBuffer[adjId + 1]] * _Scale;
float3 v3Pos = _PlacementVertexBuffer[_PlacementTriangleBuffer[adjId + 2]] * _Scale;
float noiseX = abs(snoise(float3(id.x, id.y, 0.0f) * 1000.f)) * 1.25;
float noiseY = abs(snoise(float3(id.y, id.x, 0.0f) * 1000.f)) * 1.25;
float a = (id.y % _GrassPerTriangle) / _GrassPerTriangle;
float b = (id.z % _GrassPerTriangle) / _GrassPerTriangle;
if (a + b >= 1)
{
a = 1. - a;
b = 1. - b;
}
float3 a1 = (1 - sqrt(a)) * v1Pos;
float3 a2 = (sqrt(a) * (1 - b)) * v2Pos;
float3 a3 = (sqrt(a) * b) * v3Pos;
float4 pos = float4(v1Pos + (a * (v2Pos - v1Pos)) + (b * (v3Pos - v1Pos)), 1);
this is my code atm
you can use lerp for the remap sure, you still need to also clamp thing to the lower and upper bound. Then do your logic to remap a range of (850 to 1700) to (5 to 100). Lerp is just a simple equation
https://docs.unity3d.com/ScriptReference/Mathf.Lerp.html
Also no need to worry about making this a single line of code already, you dont even have the logic down yet.
Actually for lerp, you would also need to inverse lerp to find how far your value is between 850 to 1700 in terms of a percent. Then lerp would use that percent to get the value from 5 to 100
is it incorrect then to think of "id" as a vector3 constrained to the threadgroups I used in .Dispatch?
initializeGrassShader.Dispatch(0, grassPlacementMesh.mesh.triangles.Length / 3, grassDensity, grassDensity);
can someone please tell me the bind-pose of a bone of a skinned mesh, its relative to what? is it the world matrix or some matrix relative to root node or what?
The xyz numbers you put in the Dispatch will get multiplied by numthreads. So, if you have numthreads(8, 8, 1) and you dispatch with 1, 2, 3, you will get (8*1, 8*2, 1*3) threads.
So you usually divide the actual count you want with the numthreads you've put in the shader.
But since it's an integer division, any fractional part will be removed, so you'll want to divide by float and use Mathf.CeilToInt. This means you might get extra threads invoked, so you have to add a range check at the start of your compute shader kernel and early exit if it's an extra ID you don't want.
got it, that makes sense
I'll use multiples of 8 for now while testing and do that once I've confirmed the triangle plotting behavior isn't buggy
yep, that fixed it
awesome
can i blend this with the "skybox color"
this sounds like some general purpose database to me instead of something you do from scratch - you can bring in sql or some other database that fits your usecase. supporting rw and sort throws out most naive implementations I've used in my own solutions so far (they had a set number of entities with no sorting required)
depending on the number of entities you can use a sparse array for your entities saving indices into a packed data array. that way checking for an entity present becomes sparseArray[entityId] != -1 (basically a hashset performance wise) and retrieving a value becomes valueArray[sparseArray[EntityID]] (more or less same perf as List<T> due to double dereferencing) but this really eats memory, especially if you want to use normalized tables and have many sparse arrays - on non normalized tables you may up using a lot of null entries in the value arrays.
Sorting would obv touch both arrays, adding is easy (add a new value to the value array, put the index in the sparse array) deleting is trickier if you want to recompact the value array (shifting values down + shifting indexes in the sparse array) but possible to make performant if you use a mark dirty / mark for deletion approach and clear things out over time
Hello idk if this is advanced but I have a problem with my WebGL build for my unity game. I am making a 2D platformer and i used Tilemap Collider 2D and it works perfectly in the editor but when i make the webGL build and post it on itch my player juste goes through the floor and my collisions don't work and idk what to do
Well, can you confirm the issue if you run the build locally?
yep if i do the build and run function i have the same problem
Okay. I don't think there's any difference between platforms for 2d tilemap colliders, so it must be your code. Share your movement related code. Also, it's probably not an advanced issue.
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
Here's the code but i don't understand why the problem would be in the script if in the editor it works but just not in WebGL
!code
๐ Large Code Blocks
Use links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/, https://paste.myst.rs/, https://hastebin.com/
๐ 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.
It could be frame rate dependent issue.
Where are you calling Run from?
in fixed Update
Hmm... Okay. Can you record a video of the issue?
And a video of it working correctly
heya, apologies for the ping but I figured you might have some insight
i've fixed up the actual plotting algorithm but I'm still having some trouble that I suspect might be with how I'm handling the ids
the attached picture is proof the plotting is working (points at 0,0 and 0.0625*8,0 respectively)
but this is what I get with ```
float s1 = id.y / _GrassPerTriangle;
float s2 = id.z / _GrassPerTriangle;
_GrassPerTriangle is 16, and id.y and id.z range from 0 - 16, so it seems logical to me that they should always be a spread of values, and yet they seem to be very consistently incorrect
this is with [numthreads(1, 8, 8)] and initializeGrassShader.Dispatch(0, grassPlacementMesh.mesh.triangles.Length / 3, grassDensity / 8, grassDensity / 8);
even setting id.y and id.z to a 1-16 number gets correct results which makes this even more confusing
are you sure you don't need a cast there? I would assume s1 and s2 are always 0f
well except in the case of 16, assuming you aren't modding id.y and .z by _GrassPerTriangle like you did in your above snippet
yeah, I've tried it by creating a float fId = float3(id.xyz) and using that, but same deal
I've actually managed to get it to kind of work but I'm realizing the way I'm getting the point values isn't going to work
this is with initializeGrassShader.Dispatch(0, grassPlacementMesh.mesh.triangles.Length / 3, grassDensity, 1);
which is actually perfect. it even works if I up the thread count, so this is ideal
as soon as I change the 1 back to grassDensity however
I get this... which is mapping points correctly, but using just ```
float s1 = id.y / _GrassPerTriangle;
float s2 = id.z / _GrassPerTriangle;
for points is clearly not going to fill the triangle in the way I was hoping, since it's seemingly random every time I restart the shader
I assume it's because of the semi random order the threads are executed, so I need to probably use the sum of id.y and id.z instead..? but I have no clue how I'd map that single value to two separate values
another random incorrect variant, which is, again, not that far off, but still not a uniform plotting by any means
Edit: I got it to work, i just needed to enable read/write on my sprite
Hey guys , i'm trying to write a script to set UV2 of imported meshes. I would like to use my own uv channels for lightmaps but unity keeps using its own uv's ignoring those imported. Can someone help me to write a code for that ?
im sooo confused about quaternions: why do these two arent equivalent ????
var kfr_delta = Quaternion.Inverse(ToWorld(a)) * ToWorld(b);
var kfr_delta = ToWorld(Quaternion.Inverse(a) * b);
Because quaternion arithmetic/composition is not commutative
The order in which you perform operations matters
ah yeah. makes sense.
how do i know which order to apply ?
how do i decide which one is the valid one ?
If in doubt, break the statements down into single steps and Debug.Log them
completely useless with quaternions, not intuitive at all
even if i debug them what am i gonna do?
so my problem is
gA, gB, gParent = gameobjects (gA,gB are childs of gParent)
a and b = localRotations of a & b
c = rotation of parent
how do i calculate the "difference" of the b-a rotation then put it into world?
im not sure which order is valid
that does not matter. Only the start point(s) and end point are important. what you can see, with experience, is the changes each stage appliies
Compute the world rotations of a and b. Now you need to find a rotation such that a * c = b. This should just be inv(a) * a * c = inv(a) * b --> c = inv(a) * b, since inv(a) * a = 1
I do this in a component that attaches Unity Spline knots to transforms
although I just noticed that I named these things backwards
var knotWorldRotation = splineTransform.rotation * knot.Rotation;
var toParentRotation = Quaternion.Inverse(parent.transform.rotation) * knotWorldRotation;
rotationOffsets.Add(toParentRotation);
That should really be toKnotRotation
(and that's how I use it)
Quaternion multiplication is not commutative, but it IS associative
(that's not relevant here, though)
so u are saying Inverse(ToWorld(a)) * ToWorld(b); ?
(a * b) * c = a * (b * c)
Correct.
You can read this as:
- inverse the rotation of
a - apply the rotation of
b
This is exactly like finding a vector between two points
(b - a)
Your rotation is now inv(a) * b, so a * inv(a) * b = b
Order is important.
If you multiply this on the left hand side of your starting rotation (a), you get
inv(a) * b * a
and i have no idea what that produces
thus, if you can get inv(x) and x next to each other, they cancel out
yep thats what i did, the thing is that the animation retargeting isn't still correct. tbh im not sure anymore. look this gif
im basically doing that by using inverse(parentOfAandB.rotation * a.localRotation) * (parentOfAandB.rotation * b.localRotation)
(which is equivalent to writing (-a) + b)
try it out on something much simpler
like, a cube with two cube parented to it
you want to eliminate as many variables as possible
For reference, here's my spline-parenter code. It might be useful to look at https://gdl.space/iniyemuduv.cs
alright but that's a hassle as i have to rig and animate a cube
you're just trying to figure out if this rotation calculation is working at all
eschew everything else: just write code that computes a rotation between two transforms
(and remember that toParentRotation should really be toKnotRotation)
Also, is there a reason you aren't just using a.rotation?
If you want to calculate a rotation between a and b in the parent's local space, you shouldn't be using the parent's world rotation at all
Perhaps that's your problem
although, since you're applying the same rotation to both a and b, that shouldn't change the resulting delta-rotation
yes im not using a.rotation because animations store their bone-keyframes (position/rot/scale) in LOCAL space.
basically what im doing: get the delta rotation between keyframe and first keyframe, then add it to the target mesh that we want to transfer the animation to
I would do some sanity checking by just calculating a fixed rotation with Quaternion.AngleAxis or something
to make sure that applying the same rotation to different armatures works the way you expect
heya, is anyone experienced with compute shaders available to offer some insight on this issue?
it seems like I'm getting consistent values for id.y, but not id.z, or not when used together, despite it seeming like that should be the case
Please post in the correct channel #archived-shaders
my bad, I searched up compute shaders and saw people talking about them in here so I thought it was OK
Hey guys, so I'm trying to optimize a voxel engine, which currently takes way too long to load a world. The biggest bottleneck is the loading of the texture atlas, which takes over 6 seconds. Specifically, it's the operation Texture2D.LoadImage(). I was attempting to make this an asynchronous operation, but Texture2D.LoadImage() is not an operation that can be done on a thread apparently. Unity restricts it to the main thread. As such, I don't see a way to feasibly do this operation asynchronously. Similarly, I tried to do it in a coroutine, but the coroutine isn't true multithreading so it'll execute the entire LoadImage() function before any yield returns can be called, so the end result is that its still frozen for 6+ seconds. Is there any way to get the LoadImage() function to run asynchronously in the background, without impeding the main thread?
You can load an image asynchronously lwith this https://stackoverflow.com/a/69141085
I've turned
// string atlasPath = Path.Combine(Application.persistentDataPath, "Maps", PersistentDataManager.Instance.Map, "Atlas", "UVChecker.png");
if (!File.Exists(atlasPath)) {
Debug.LogError("Texture atlas file not found at " + atlasPath);
return;
}
byte[] fileData = File.ReadAllBytes(atlasPath);
Texture2D atlasTexture = new Texture2D(2, 2);
if (!atlasTexture.LoadImage(fileData))
{
Debug.LogError("Failed to load texture atlas from file data.");
}
atlasTexture.wrapMode = TextureWrapMode.Clamp;
atlasTexture.filterMode = FilterMode.Point;
atlasTexture.mipMapBias = 0f;
material = new Material(Shader.Find("Standard"));
material.mainTexture = atlasTexture;```
into
```private IEnumerator LoadTextureAtlas()
{
string atlasPath = Path.Combine(Application.persistentDataPath, "Maps", PersistentDataManager.Instance.Map, "Atlas", "Packed_Atlas.png");
string uriPath = "file://" + atlasPath;
using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(uriPath))
{
yield return uwr.SendWebRequest();
if (uwr.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"Failed to load texture atlas: {uwr.error}");
}
else
{
Texture2D atlasTexture = DownloadHandlerTexture.GetContent(uwr);
atlasTexture.wrapMode = TextureWrapMode.Clamp;
atlasTexture.filterMode = FilterMode.Point;
atlasTexture.mipMapBias = 0f;
material = new Material(Shader.Find("Standard"));
material.mainTexture = atlasTexture;
}
}
}```
However, it still lags and freezes for a good moment
my guess is that downloading the texture takes a shit load of time
specifically because the atlas in question is a massive 16k x 16k image
I had definitely not considered an in-memory database; that's not something I have ever considered for use within a game client.
Hi friends, I have one script that converts all game objects with a MeshFilter into the 3D model (.fbx), but this script converts all the MeshFilter into separate meshes for example if 5 Meshfilter have the same mesh then these scripts generate 5 separate mesh into generated 3d model. Please help me to optimize this script. Thanks https://hastebin.com/share/gaduyahaxu.swift
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
Just put the meshes in a HashSet to track the ones you've already seen. Skip them if they're already in the set
What would be the best way to handle spatial partioning for instanced objects without too much overhead?
Depends on your need for sure, but most known method will be without too much overhead or have parameters to balance everything.
Hey guys, i'm trying to figure out how to use IAP without using Unity's Game Services :) I would appreciate if someone could point me in the right direction!
Simple tiling is the easiest
Just divide position by your tile size and round to int
Each of those tiles will contain a list of the data to pass to Graphics.DrawMeshInstancedIndirect, right? Wouldn't I need to either merge all tiles within view into one list before passing or have multiple calls to DrawMeshInstancedIndirect?
keep me posted what you eventually go with to solve this problem - always curious how others solve more data oriented problems. Way too little insights about that around
I highly doubt an in memory database is the way to go if you are looking for performance. In general, specialized solutions are going to be more performant than generalized solutions, and databases are very generalized. On top of that, there are lots of features databases implement (eg ACID transaction) that are overheads but irrelevant to the problem.
while true, you also need to consider the implementation overhead of this specialized solution, and their number. having very performant presence checks, RW and sort is non trivial, and potentially worth considering a less runtime performant solution which instead saves a lot of developer hours
especially if you want to maintain data coherence over time so performance does not degrade due to data fragmentation, further complicating implentation of the specialized solution
That's fair, and is why the first thing I suggested for them to look at is their access pattern. Eg if insertions and deletions access far outweighs sorted lookup access, they can only sort on lookup rather than on insert/delete.
Without knowing their specific access pattern, there's no other solution than a generalized one. And a generalized one as you said, is difficult to implement and maintain.
๐
i wanna do something complex but i don't know if it will work, a script that checks if any headset or headphones are plugged in/connected on the pc, and if one is detected, it activates a headset (as a gameobject) on the player
Hello, im trying to use Graphcs.RenderMeshIndirect but I got into two issues.
1- When i set a camera in the RenderParams struct, the rendering starts to flickers. I need to set a camera to accuretly perform Frustrum Culling, both in scene and game view, but it starts to flicker on an off outside play mode. Im launching the rendermeshindirect in late update.
2- Im setting the ViewPort matrix for frustrum culling, but it seems to be losing the position of the camera? Not sure why but it's acting as if the camera was always at 0,0,0 but the rotation is correct.
NativeArray currently doesn't support ref return but it does provide NativeArray.AsSpan
so if I'm doing something like this:
var array = new NativeArray<float2>(new[]
{
new float2(0, 0),
new float2(0, 0),
new float2(0, 0)
}, Allocator.Temp);
var span = array.AsSpan();
span[2].x = 10f; // now array[2] is float2(10, 0)
am I doing something illegal, are there any pitfalls with this approach. is this just bypasses safety checks or something worse?
for atomic types it's obviously not that critical but for big struct can be useful
Could be wrong but I dont think theres a way of really checking if it's a headset, compared to just a speaker. but you'll need to see if there's any library that does this. Is this a hard requirement or could you just have some toggle where the player chooses if they have headphones on their player?
Well some friends suggested me Naudio but i dont know how to get it, Because of i understood Naudio act like a audio manager or somethin
Even with this I dont think it has a way to say if something is specifically a headset. There is simply an audio port and it knows if something is connected
No, this is fine.
Yeah..well maybe a script that detect the current audio port and if it detects a new one, it activate the gameobject?
hi guys
i have this code for combining splatmaps
void CombineSplatmaps(TerrainData mergedTerrainData)
{
ISet<TerrainLayer> layers = new HashSet<TerrainLayer>();
foreach (TerrainLayer layer in data.terrainLayers)
{
layers.Add(layer);
}
mergedTerrainData.terrainLayers = layers.ToArray();
int resolutionFactor = 8; // 8x8 formation
int cellResolution = 512;
int targetResolution = 4096;
float[,,] cellData = data.GetAlphamaps(0, 0, cellResolution, cellResolution);
float[,,] splatmapData = new float[targetResolution, targetResolution, mergedTerrainData.terrainLayers.Length];
for (int y = 0; y < targetResolution; y++)
{
for (int x = 0; x < targetResolution; x++)
{
int sourceX = x / (targetResolution / (resolutionFactor * cellResolution));
int sourceY = y / (targetResolution / (resolutionFactor * cellResolution));
for (int layer = 0; layer < mergedTerrainData.terrainLayers.Length; layer++)
{
// Transfer and blend the splatmap data from the original terrain to the merged terrain
splatmapData[y, x, layer] = cellData[sourceY % cellResolution, sourceX % cellResolution, layer];
}
}
}
mergedTerrainData.SetAlphamaps(0, 0, splatmapData);
}```
and well, the problem is, for each individual terrain i need to build 4096x4096 heightmaps from 512x512 pieces
which is 16ย 777ย 216 writes to the splatmap array, and the same amount of reads ig
is there a way to use these 512x512 pieces but combine them so resulting heightmap is 1024 for example
like a downscaled version
i kinda need to do that at runtime, so i can definitely go for the compute shader
my goal is to show a 256x256 heightmap when terrain objects is reeeeally far, and show 4k when player is standing close to the terrain(around 100 units from the corner)
Not totally sure about your question directly but this task looks extremely parallelizable, no?
Well, the problem is
I have 144 terrains for the entire world
And if i keep all of them with splatmap of 4k, i will never have enough RAM/VRAM to store all this data
I ofc can parallel the calculation thing and even move the computations to the GPU, but i need to somehow transfer 8x8 grid of 512x512 alphamaps into a single 2048/1024/512 map(with quality loss of course)
And idk how to achieve the quality loss
Then maybe it's a job for streaming? You only load 4 of the terrains from the disk at once and unload them once they're far enough.
I don't want to unload them, because i want to keep distant terrains visible but low quality
Aren't these very well known algorithms? Like cubic bisampling etc?
Well, you then just load a smaller resolution mesh/texture.
If there is a way to implement it inside the float[,,] operations with transferring and merging smaller maps, i'd like to use it
I have a low resolution mesh, which works great
And also i dynamically set the pixel error and use distant fog to hide small geometry updates
The point is loading/unloading from disk to save on the used memory.
So there is a way to load alphamap from disk and apply it to terrain
Well, if you dynamically rebuild the alphamap, you will also save overall allocated memory
And you can avoid disk loading operations this way
And well, in case you are high in the sky, most of terrains can stay on 512 splatmap, which means they won't eat a lot
Depends on the implementation. If you're using unity terrains, I'd imagine that you'll need to load/unload the whole terrain object and it's dependencies. If it's a custom terrain system you can have more control.
I can just have heightmap, layer set and alphamap saved
I imagine that unity keeps the full res splatmaps in the RAM at least.
It won't if you don't let it
Well, as i think about it, i need to keep the 64 small pieces with 512x512 alphamap 144 times...
Which means a lot of memory wasted anyways
More than my pc has probably
My calculations brought me to 72 gigs xd
Trying to instantiate some foliage procedurally, I can't get the rotations right.
var normal = _terrain.terrainData.GetInterpolatedNormal((x + halfSize) / _terrain.terrainData.size.x, (y + halfSize) / _terrain.terrainData.size.y);
//grass.transform.rotation = Quaternion.Euler(0, UnityEngine.Random.Range(0f, 360f), 0);
var target = normal - grass.transform.position;
grass.transform.rotation = Quaternion.LookRotation(target, grass.transform.up);
Their rotations seem to vary a little bit but are within a very close range
Any ideas?
Hi. Does anyone have any experience trying to use code generation through Cecil when deploying for IOS? I want to modify all properties with [Notify] attributes and add some code to the setter method to invoke property change events. I've been able to do this for Windows by using IPostprocessBuildWithReport and simply modify the assembly post build. But how can I intercept that when building for IOS so that I modify the assembly before it's converted into Xcode project?
SOLUTION: I found out that you can use "IPostBuildPlayerScriptDLLs" to intercept the assemblies before making xcode project.
I've been working on implementing scene streaming (additive scenes) and combining that with a save/loading feature. One of the parts of the implementation is a ScriptableObject that is a map between a key (string) and a Prefab (located in the Assets folder, not the scene). When i load a savegame it works in the editor, but I just found out by debugging that in the player build i can not Instantiate(prefabMap.value) due to the reference to the Asset Prefab being the string "null". To load my game i load a single scene "Loading" and then reload the active scene. I'm guessing that the ScriptableObject values gets garbage collected and lose the reference?
I've looked at the Addressable package and it looks like it might be able to solve this, however, I would really like to keep the scope of my project as limited as possible. Any recommendations?
I was not able to make it work, either in editor or during command line building. Looking into IPostBuildPlayerScriptDLLs now which looks promising. I'll update when I find out more.
There is also an undocumented API to hook into assembly post processing called IL Post Processing. Many Unity packages, like Entities and Burst, use it, and some third party plugins too, like Mirror Networking.
It works in both the editor and builds and runs in parallel with other IL processors in parallel.
There's some information about it here:
https://forum.unity.com/threads/how-does-unity-do-codegen-and-why-cant-i-do-it-myself.853867/#post-5646937
Hello!
Two things first:
Sorry if the title is confusing. I'll clear it up soon
And I'm also sorry if this doesn't really apply to the Entities stuff...
Also very useful to look at Unity's packages and how they implement it.
https://github.com/needle-mirror/com.unity.burst/blob/master/Unity.Burst.CodeGen/BurstILPostProcessor.cs
This is a bit specific but, if I instantiate an object inheriting from PointerManipulator in an EditorWindow, after closing the window, does the Pointer Manipulator persist in the editor or does it get deleted?
Apparently they persist until a reload of the editor
im up to code again
so, my idea is to support modding in the game. I provide users with a kit to modify each 64x64 cell individually, and i keep 512x512 alpha map on each cell for modders to paint textures on the terrain.
When I start the game, I merge 8x8 cell grid(where each cell is 64x64) into a single 512x512 chunk so I get 64 times less objects on the scene at the same time. These big chunks have increased alphamap/heightmap resolutions to match the quality. So right now with 512x512 alpha maps on each small cell i get 4096x4096 final alpha map.
and well, since i'm making a large world(6144x6144), it consumes around 72gigs of ram, and well, that's too much for most of PCs xD
So i decided to make is so when game starts, alphamaps of all terrains are on lowest quality i allow(256 on a giant chunk)
and only ones which are close have the entire 4096
but that means i need some way to dynamically rebuild the alphamap as player approaches the chunk, and well, rebuild it not to 4k all the time, but to 512/1024/2048 versions based on distance
i made the distance code with some workarounds and it works fine
but the only part left is the actual map building
i can probably load pieces from asset bundle, change their map to a lower one and then go for building as i do rn, but with lower-res
Making objects static or using GPU Instancing doesn't seem to affect my batch count at all, although I'm changing a lot of objects
only saved 2 when pretty much the entire scene's meshes are static
isn't it saving only if you have same mesh/material a lot
also make sure your static batching is enabled if you are using static objects, or disabled if you are using gpu instancing(not sure but afair static batching should be off in that case)
I have a lot of objects using the same things, I have a modular kit I've made, so objects repeat themselves
can some1 help me for making a good isometric placement system? unity 2D
ive been lookin everywhere
Might want to look at the profiler a d frame debugger instead. Stats window is unreliable for inspecting batches, especially on SRPs.
Use Unity's Grid component. It does all the hard math for you.
but making your own world grid is fun
Yeah but i have no clue on how to use it
Cause like
I want it to be able to have a grid at a custom size
And make it to be able to place gameobjects
And move em
is there a way to make unity serialize an external class (from external dll) so that i can see it in inspector ?
is the class serializabhle?
no its from external dll unrealated to unity
custom editor
tough, take it or leave it, up to you