#archived-code-advanced

1 messages · Page 123 of 1

untold moth
#

You can extract the rotation from the matrix. There should be unity API to do that. You'll need to look up the exact API though.

steel snow
#

how do you assign to unity recompilation? I have native containers i need to dispose if i recompile code but on disable and on destroy doesn't get triggered when i recompile. So the containers are not disposed of.

#

im constantly getting leak warnings as a result

steel snow
#

thanks

frigid orbit
#

I feel like I have generally 3 types of methods in scripts

Main ones defining main jobs this script doing, usually public called outside or private put in Update like general Enemy TakeDamage or AgressiveState from fsm
Big to medium private ones which are usually an abstracted away functionality of main ones like isCanShootPlayer (I wonder if I should consider renaming those, is isCan bad construct?)
Small private ones which are abstracted away chunks bits of code above which happened to be used in several other methods

Now the problem is it gets muddy when I am redacting those scripts, bigger script file is the worse
When revisiting I usually want to see only main methods, however when I am redacting main one I want to see the smaller relevant to it nearby, and when I am redacting smaller ones I want to see the smallest relevant ones nearby...
How do I even structure code? Are there any articles on this topic you can recommend to read?

untold moth
#

You'd generally use your ide features to navigate through code. For example in VS, F12 to jump to the method definition. Then there's "go back" button. You should also configure different short cuts. For example, alt up/down to navigate to the next occurrence of the symbol, alt left/right to navigate to previous viewed position.
As well as use context menu commands, like find references. With such features you can easily navigate your code and edit it conveniently.
Also, if you need to view your methods to remember what they do, the naming is probably bad, or comment docs should be added.

slow jay
#

trying to investigate a memory leak with run-time Texture2ds not being Destroyed after use. I took 2 snapshots: A is from the lobby and B is from actual game session, when Texture2ds are created.

B has 300mb difference in resident memory, but the memory profiler doesn't show where that 300mb is allocated. Why? Is there a way to figure it out?

#

Is it possible that the texture2ds that weren't destroyed are now "Hidden" and Unity only knows that they are taking 300mb? but it doesn't know they are Texture2ds?

sly grove
dusty wigeon
slow jay
dusty wigeon
sly grove
plain gate
#

If i want to use a compute shader to generate vertex data and pass that to the vert/frag shader. What would be the easiets way to do that?

sly grove
plain gate
tranquil quail
#

I want to disable hand tracking in my game on Quest. It's a controller-based game, but when I double tap my controls together, hand tracking turns on and my players can't play until it turns off again. I know Gorilla Tag has this turned off, so it should be possible.

I'm using the OpenXR plugin, and have hand interaction poses turned off.

Anyone know how I can turn it off?

plain gate
#

Do Graphics.RenderPrimitivesIndexed and Graphics.RenderPrimitives essentiality do the same thing. I see in both they are passed a position and triangle buffer.

pale nebula
#

Hello everyone, sorry for bothering you. I'm working on a project with Unity Render Streaming. I've managed to interact with the UI, but I can't find a way to interact with objects. Specifically, I want to click on a 3D object to make it disappear. Does anyone know how to do this? Thank you!

sly grove
pale nebula
#

oh it's work, thank you

paper grotto
#

I'm creating a tool that automatically adds a scene to the build list if it isn't already included. Unfortunately, it appears that SceneUtility.GetBuildIndexByScenePath doesn't update right away. Is there any way to force an update?

paper grotto
#

Alright, after some testing, I realized it doesn't have anything to do with frames. Before Unity enters PlayMode, it makes a build of the game. It doesn't matter if editor code adds a scene to the build, if it happens during runtime that play session won't see the scene in the build.

#

Is there a way to add the scene to the build list before the editor enters play mode? I've tried both [InitializeOnEnterPlayMode] and [InitializeOnLoad], but both happen too late for changes to the Build scenes to affect the play session.

untold moth
compact ingot
slate spoke
#

I'm doing some procedural terrain generation with indirect mesh renderers on every terrain chunk. For reasons I can't figure out, when it initially loads, it renders every chunk's plants where the 0,0 chunk is. However, as you can see in the video, whenever I update the code for that indirect mesh renderer (regardless of if it changes any of the actual code), all the plants start rendering on the correct terrain chunk. Wtf is happening?

#

The coordinates being passed to the renderers are relative to the position of the chunks they're attached to, until I mess with the code like I did in the video, they all seem to render in world space instead of local space

pale nebula
#

Can you tell me how to set up multiplayer for Unity Render Streaming? For example, the Unity multiplayer sample on GitHub doesn't work, and I can't find any tutorials. Thank you.

midnight violet
inland wave
#

Hello everyone, sorry to bother you, but I need your help. I'm working on an online car game in Unity, and I'm facing some issues that I really can't fix on my own. The problem is that I can't get the cars to spawn on the map chosen by the players in the game. Only the host is able to spawn their car on the map. Let me explain the car selection process.

We have a "Host" scene to create a game, then we move to a new scene, which is the lobby. The host creates a game that players can join. Once the players have joined, the host starts the game, which loads a "Game" scene where the menus are displayed, meaning the map selection, then the car category, and finally the car selection. After that, we click on "Play," which loads the map scene and removes all other scenes.

And it's from the map scene that everything bugs. In other words, the cars don’t spawn, even though I set them up with the required Mirror components.

I'll leave my GitHub here—if you could take a look, that would be really great.
https://github.com/scotty800/lobby

GitHub

Contribute to scotty800/lobby development by creating an account on GitHub.

compact vault
#

pretty sure there's a seperate server for mirror issues

inland wave
#

thanks man

worldly hull
#

Hi there, does anyone know if MarkerFlags.ScriptDeepProfiler is usable by the end user in any way?;

sly grove
upbeat garden
#

Can you all think of a performant way to store a collection of different MonoBehavior Component references (of different types), and then to access those component references by their specific types later, without casting?

#

Obvious answer would seem to be “No, not by normal means.”

But I feel like maybe I’m missing something..

#

Maybe UnsafeUtility.As<T, U>()…which I believe does a cheap, C-style cast…but am I being stupid?

dusty wigeon
upbeat garden
#

That may be. But this would be a hotpath, and I’m at least looking for a way to avoid it.

dusty wigeon
#

Start by profiling before assuming, you might find that it does not cost a lot and that whatever funky method you try is actually costing more.

#

Low level performance is kinda complicated and it is easy to forget a factor when attempting to optimize.

upbeat garden
#

That is always good advice, ty.

Do you have any ideas about direct solutions to the original question?

dusty wigeon
#

It depends on the whole context, but usually you want to store them continuous without polymorphism for the best performance.

#

Otherwise, you can use __makeref to convert from <T> to <U> without boxing if you are working with value type.

upbeat garden
#

You know…you answered me, which I appreciate. But I never know how to respond to someone who:
1- second-guesses the validity of someone’s whole question, and
2- doesn’t read the question

You answered some other question. I’m not sure why.

compact ingot
#
  1. see 1
upbeat garden
#

I…did not consider that. Sorry folks

compact ingot
#

but to be fair, if you ask in advanced and use the right terminology, people will take you seriously

upbeat garden
#

You’re saying I didn’t use the right terminology?

compact ingot
#

no, just in general

upbeat garden
#

Ah, Roger that

#

Well, I’ve certainly acted a fool here. Apologies, @dusty wigeon

compact ingot
dusty wigeon
#

The real issue here, is that you asking to optimize an hotpath of code but the way you are going about is wrong. If you want optimize code, you should use DataOriented approach. Otherwise, it feels like you are not that serious about optimizing it.

upbeat garden
#

Big can o worms there. :p

dusty wigeon
#

Which makes thing like casting, as far as I know, not really a big issue, feel silly.

upbeat garden
#

There’s only so far towards DOD you can go, when working in MonoBehavior land. :p

compact ingot
#

using a monobeaviour in the first place makes most other optimizations futile

upbeat garden
#

I wish DOTS was in a more mature state

#

I would strongly prefer to use it, fwiw

compact ingot
dusty wigeon
#

You can use an hybride approach also.

compact ingot
#

you can get very very far with .jobs, .burst, .mathematics and .collections

upbeat garden
#

I’d love to talk to people about this subject, but it’s a pretty deep one. I’m not sure I have time on my lunch break. :p

I guess the short answer would be:

  • close to 10 years of development, without clear communication from Unity about plans for future feature support/parity with GO Unity.
  • lack of support for some common, important features like Navmesh, UI, Animation, and others. Working with DOTS for core game logic, on anything besides a small or hobby game, it’s easy to run into a minefield of compatibility gotchas - some of which you might not hit until late into development.
  • the necessity to roll your own versions of major features, which GO unity users have access to without issue.

For a company with a team to pay, DOTS unfortunately still represents a large production gamble, even though I am a huge fan and cheerleader.

#

I’d also push back against the idea that there’s no point in optimizing a GO-based game. That…doesn’t make sense to me.

Most all Unity games are made with managed, GO, OOP code. And I’d bet all of them optimize their hot paths.

compact ingot
#

DOTS (minus entities) is used everywhere in unity when performance matters.

upbeat garden
#

And where data isn’t stored in Mono components

compact ingot
#

and you don't need entities to be data oriented

upbeat garden
#

I’ve been in DOTS land for too long. Do people working on non-DOTS projects not store the majority of their data in MonoBehaviors anymore? Maybe I’m out of the loop.

#

I hear about people using Bursted jobs on their own in GO-based projects. But I figured those must be being used in isolated cases, where data was intentionally stored separately from MonoBehaviours, to make that possible.

upbeat garden
compact ingot
# upbeat garden Would you mind explaining more what you meant here?

data orientation is about writing code in a way that its execution causes fewer wasted computation on the CPU, primarily due to cache misses which force a page load from main memory which makes the CPU core wait 20-100 cycles while doing nothing. you can optimize your code to do that without any fancy libraries

upbeat garden
#

I understand. I meant…due to the existing data layout of GameObjects and their Components, it’s actually difficult to work in an optimized DOD way with GO-based code…at least, not without avoiding the use of Components and rolling your own data structures.

#

At least…compared to unmanaged ECS, GO optimizations are kind of a drop in the bucket

compact ingot
#

if you don't access the gameobject or component through a reference, they do not impact your algorithm

upbeat garden
#

Oh, got it

#

…how does one access a GameObject or component though something other than a reference?

#

(Without unsafe code)

compact ingot
#

you dont

#

think of it as a mesh, which is just a bunch of primitive structs/types in arrays, you can make operations on them extremely fast without ever touching the components they sit on while doing so

upbeat garden
#

True. But you’re going to incur fetching costs just by accessing the mesh in the first place.

compact ingot
#

not necessarily

#

you could access the raw data pointer, but thats maybe a step too far

upbeat garden
#

If it’s stored in a MonoBehavior

compact ingot
#

the point is not to avoid the copying, the point is to avoid random memory access while doing math

compact ingot
upbeat garden
#

Tbh, these sound like micro-optimizations, compared to the unmanaged sequential layouts of DOTS ECS code.

compact ingot
#

what do you think an array is?

#

its a sequential layout of data

upbeat garden
#

You didn’t let me answer! :p

compact ingot
#

whether you make that array yourself or get it from entities doesn't matter

#

entities uses the same APIs, there is no magic

#

you can access all that stuff without entities

upbeat garden
#

“…at least, not without avoiding the use of Components and rolling your own data structures.”

compact ingot
#

idk what you are really arguing here

sly grove
#

There's a difference between having logic on a component and having logic/data on individual instances of components

azure moss
#

I am trying to make navmesh generation

#

based on A* grid

#

I managed to make it to some extend

#

however for large map, when I do it in chunk, there is this weird gap

#

What is the way to solve it?

echo coral
#

For these perf benefits you need an array of structs but with a lack of pointers you need a better way to reference them... like an id...

quartz galleon
#

What the hell?

austere jewel
#

This is a programming channel

lofty falcon
#

Anyone know if it is possible to debug a native dll in Visual Studio? It's my dll and I have the pdb

#

I guess I can setup a normal C# project, but I was wondering if there is a way to do it inside of Unity

untold moth
lofty falcon
#

Okay thanks, I appreciate it!

echo coral
#

If you have a Vs project for the native DLL you can attach and debug just fine

#

Does require an editor restart though if you recompile it as only managed ones can be reloaded

novel plinth
novel plinth
#

why you want to do it on components? it makes sense on structs tho

upbeat garden
#

Thanks for replying. I...am pretty sure this will sound like one of those answers that immediately screams "your design is wrong.". And maybe it is. I'm investigating a potential new architecture for some code, and figuring out pain points.

In that design, I've wound up with a case in which I need to store a map of Components, but then access them later as their derived Component type. Why not just store Type-specific references somewhere? Good question, but it would be an involved explanation. Not claiming any smarts here.

#

If I read that case about someone else's code, I might think "That design sounds suspicious.". Which is probably a sign that I'm on the wrong track.

#

Although...as best I can tell, GetComponent() also does a pointer reinterpretation behind the scenes. And I don't think that's the expensive part of that function. So if I'm only doing this at the same frequency as someone might call GetComponent(), then maybe it's not so smelly? Hmm. :/

echo coral
#

well unless you notice perf issues with casting classes a lot or encounter lots of failed casts at runtime its probably fine

dusty wigeon
dusty wigeon
#

It really is far from getting a reference in a list.

#

So if I'm only doing this at the same frequency as someone might call GetComponent(), then maybe it's not so smelly? Hmm. :/

#

This is smelly.

#

For a hotpath code at least

#

Otherwise, everything you just said before is overengineering on so many level.

upbeat garden
#

I appreciate that. Can you explain further?

dusty wigeon
#

GetComponent should never be called in a "hot path". If you think you are approach is similar in performance as GetComponent and you feel it is not an issue, then you are either not in an hotpath or you have really,really low performance requirement.

#

Which would means that casting a reference is in no case an issue.

upbeat garden
#

I would never call GetComponent in a hotpath, nor did I ever say that.

dusty wigeon
#

Alright, maybe I understood it wrong. I believe you were asking about hot path code earlier, and you were now saying that whatever you do might be similar to GetComponent.

#

Anyway, if you want more information you should start by profiling, giving more context and actually being ready to invest time in other programming paradigm. My bad, if I misunderstod.

upbeat garden
#

No worries. I’ve been hotheaded lately, and it’s stupid. My apologies

upbeat garden
#

Yeah…that pattern is pretty smelly. :/ :p

#

How do you folks reconcile when people say both “that’s code smell”, and also “don’t worry about it unless it causes perf problems when profiling.”?

When is “that’s code smell” a big enough problem to not even implement?

echo coral
#

In this particular instance I think its fine. A similar example could be a service provider which would also involve getting and casting to some derived type.

upbeat garden
#

I guess there is is a way to avoid the cast, using a static generic class. Something like:

public static class ComponentStore<T> where T : Component
{
static Dictionary<GameObject, T> componentsByGameObject;
}

#

That would spread out the references a lot more than a single Dictionary<TypeID, Component> though. So it may end up actually being slower than casting.

compact vault
#

!code

echo coral
#

if you have many instance of type T it may be worth it but why do you need GameObject as the key?

thorn flintBOT
upbeat garden
#

What key would you imagine instead?

#

I could use a UUID associated with the GO, but that’s essentially the same approach

echo coral
#

im trying to imagine when you would have GameObject instead of T to begin with

#

if you need T all the time then work with T

upbeat garden
#

My underlying challenge is that I’m trying to use some ECS-style patterns in a GO/Monobehavior world, in which systems iterate over applicable GOs, and do work by accessing their Components.

Those systems can’t very well store references to every GO’s Components ahead of time (and the GOs being worked on could change each frame anyway).

And the GOs themselves don’t store references to all of their components ahead of time. I would need to write a unique MonoBehavior for every different combination of Components a GO could have on it, in order to do that in a way that avoids casting.

…Hope that made some kind of sense in text.

echo coral
#

well managed class references in a dictionary isnt gonna achieve this so its not worth doing

upbeat garden
#

Isn’t going to achieve what, exactly?

#

Seems like it would functionally work, no? (Performance is another story)

echo coral
#

well it sounds like you are trying to do an ecs like pattern but in a way that does not yield its perf benefits

#

might as well just use ECS and Entities for real

upbeat garden
#

That’s definitely true. I don’t ever hope for anything except ‘decent’ perf when using GO-based code to begin with.

I’m using this pattern for some logical benefits. The way the code is organized.

My hope here isn’t to reach DOTS levels of performance. Just to avoid terrible performance. :/

I would absolutely be using DOTS, if it was more ready for prime time. :/ I’m back on managed land, after trying to make DOTS work for our needs for literal years, unfortunately.

#

But that’s a larger topic. :p

echo coral
#

If you start using structs for your data/components then it may start to make sense but ECS for unity has lots of code gen and use of native code to further increase performance gains

upbeat garden
#

It’s not what DOTS can do (of which I’m a huge fan). It’s what it can’t do - which includes some very basic engine features, lots of late-in-development gotchas, and poor communication from Unity about what we can depend on in the future.

#

For reasons like that, it’s just too large of a production risk for a company like ours, unfortunately. Believe me, I am a DOTS stan. 🙂

#

…I could use code generation to solve my problems here (generating custom components to hold the references I need).

..I was trying to avoid that for some reason. I’m not sure why…I guess I thought that would be code smell too. Not so elegant?

But maybe the straightest line solutions are the best, and it’s best not to worry for too long about it

echo coral
#

I'm not sure what you should do but really think hard about what you do and if it will yield any benefits

upbeat garden
#

Thanks for spending some time on it.

echo coral
#

it sucks how much effort it takes to yield nice perf benefits due to managed code but thankfully unity have quite a few solutions now such as jobs, burst and native collections

willow elk
#

https://paste.ofcode.org/nqz85WMFNzWrL4peW5XCBC
guys i wrote this custom hlsl for a custom node in unity shader graph for a toon shader
it has worked fine until i tried to covert the last part for work with foward+ render path
its working but only with large light covering a big obeject some help ??

exotic cosmos
#

yoooo, anyone wanne see mine (selfmade) dungeon generation? (idk if thats "advanced", but im proud af of it)

exotic cosmos
whole plaza
#

How can i handle Multiplayer to only send info of other clients it can see or like are close to a corner to the client from a server ?
Im using Purrnet, but a general C# idea of how to do this would be helpful as im struggling to implement this as a "anticheat" thing, while also keeping the clientside prediction and serverside rollback working

echo coral
regal lava
#

My solution would just make the server raycast from each peer to then determine if any two of these peers would be visible to each other. But, this be not be accurate enough if we're just determining if the pivot itself is revealed and not the whole player mesh, so there would be some extra logic needed.

regal lava
#

I guess occlusion culling could determine it, but you're leaving it up to the server to create a depth buffer for each of these players to determine what's occluded from their viewport.

haughty saddle
#

Hi!

I get editor crashes after trying to read a disposed NativeArray element from managed code. Is this expected behaviour?

#

editor.log:

Obtained 29 stack frames
0x00000179f005e3f6 (Mono JIT Code) (wrapper managed-to-native) System.Buffer:InternalMemcpy (byte*,byte*,int)
0x00000179f0059dcb (Mono JIT Code) System.Buffer:Memcpy (byte*,byte*,int)
0x00000179f005c063 (Mono JIT Code) string:memcpy (byte*,byte*,int)
0x00000179f3208e13 (Mono JIT Code) Unity.Collections.LowLevel.Unsafe.UnsafeUtility:ReadArrayElement<Foo> (void*,int)
0x00000179f3208b8b (Mono JIT Code) Unity.Collections.NativeArray`1/Enumerator<Foo>:MoveNext ()
(...)```

not sure why there is a string:memcpy etc.
#

i surely get a feeling that it was never intended to use native collections outside of jobs. there are safety checks in jobs, it will throw an exception at you when you try to run a job with a disposed container afaik.

crisp temple
#

Anyone know if there's a way to reduce GC alloc to 0 when using Awaitables like this example in the Unity docs? I call it every frame, idea is I have a job that I want to start at frame x, then complete it on frame x+1, but it's seemingly allocating every time I call it.

{
    // Wait until end of frame to avoid competing over resources with other Unity subsystems
    await Awaitable.EndOfFrameAsync(); 
    var jobHandle = ScheduleSomethingWithJobSystem();
    // Let the job execute while the next frame starts
    await Awaitable.NextFrameAsync();
    jobHandle.Complete();
    // Use results of computation
}

JobHandle ScheduleSomethingWithJobSystem()
{
    ...
}```
#

Unity docs say "Calling an Awaitable-returning method usually doesn’t allocate memory, since Awaitable instances are pooled by default." which I'm not seeing in the profiler, it always seems to alloc

violet valve
echo coral
#

though suprising it was not caught on the managed side to prevent a crash

novel plinth
compact ingot
crisp temple
novel plinth
#

again how many of them you're awaiting at once...

crisp temple
novel plinth
#

cant say much than just weird... sadly

crisp temple
#

All good, thanks for the info.

crisp temple
compact ingot
novel plinth
#

dont thread, let others see it here

crisp temple
#

Is where I'm calling it

#

And the actual method is

novel plinth
#

now send the screencap of said alloc in the profiler

crisp temple
#

Only other thinking is do I need to call it some other way than by just using the method name

novel plinth
compact ingot
crisp temple
#

Yeah dw I'm not going into reflection or crazy stuff, I'll just turn it back into a non awaitable before I do that

novel plinth
# crisp temple

I mean, those are zero alloc...
the allocation is from unrelated stuff (non awaitable stuff) in that method

#

so its you homework now to trace them down

compact ingot
#

well, what you're doing by calling it withou await is basically creating a dangling thread without anything holding a reference to it, so thats generally considered bad and you should if possible create wrapper around it or await it inside an async context

novel plinth
#

the continuation is guaranteed back to the mainthread

#

unless you do Task.Run OR task Factory then thats another story

crisp temple
#

Splitting off the exact same code that's in the async to the normal LateUpdate() loop, 0 alloc ever

novel plinth
# crisp temple Better example. Pretty sure it is the async pool allocing (but weirdly, not ever...

lots of pooling implementations that are using weakRefs would not hold the pooled objects for long, simply bcos there's a risk those objects accidentally promoted to gen2 already(note gen2 dont exist in IL2cpp, it is in mono OR future CoreCLR if unity finaly done with the migration).

also note holding unused objects for long would cause memory abstraction which might hurt the perf much later on. so cleaning them up once in a while would be a good practice and totally makes sense

note, I'm not sure if unity is weakref-ing here nor do I know in details about the awaitable<T> impl, but from technical pov, cleaning them up once in a while is what myself would do too.

novel plinth
crisp temple
#

Yeahh I feel like there's a way they could make it a lot closer to 0 alloc than it currently is, oh well, it is a new feature after all so I should expect it's a bit like this

#

I feel like there is probably an easy way to do what I'm trying to do, which is start one job per frame, and just run it off the main thread, then by the end of the frame grab the results, without alloc

novel plinth
#

imo their AsyncMethodBuilder being a ref type is a bad decision. They should make it struct instead and no need to be pooled...

which essentially what UniTask is doing

echo coral
#

UniTask being the best solution still for async in unity 😆

crisp temple
#

Ended up putting it all into a coroutine... 12 bytes/frame which I'm sure technically I can live with, but yeah annoying there's not a 'perfect' solution :/

compact ingot
crisp temple
echo coral
#

reading your initial code you schedule the job, you wait a frame and go "fuck it ill wait for its completion on the main thread"

#

with unitask you can await the job completion so it can execute and not block the main thread needlessly

jaunty compass
#

idk if this is an advanced issue but it feels like it is
unity raycast cant return UV from convex mesh or pretty much any mesh that isnt a non convex mesh collider
This normally wouldnt be a problem, however my game uses a funny little destruction system which heavily relies on texture modification during runtime, i have a huge issue where my vehicle is meant to be a rigidbody, but for it to be a rigidbody, it must not have a non convex mesh collider, however, my destruction script gets UVs from the vehicle, but it cant do that if its a rigidbody because then the mesh colliders are convex.
There is a paid asset on unity asset store that adds support for non convex mesh collider rigidbodies, however im pretty sure it cant return UVs because it isnt mentioned anywhere that it can.

#

the best solution i can think of right now is having a non convex mesh & collider for my car, that basically gets teleported to it and then returns proper UVs i can then use on the visible vehicle parts

haughty saddle
sly grove
#

This isn't a bug

jaunty compass
sly grove
#

Like pre baked collision damage areas

lofty falcon
#

Do native to managed callbacks have to reference static delegates?

The Unity Editor is crashing sometimes when the callback is invoked on an instanced object.

I didn't have this problem in a normal .NET console app so maybe a mono thing?

Example:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void NativeDefaultDeviceDelegate(IntPtr deviceId, IntPtr friendlyName, uint role);
jaunty compass
pliant belfry
#

Hi, guys! I have a player controller with more than 2,000 lines.

Can anyone recommend some cool content to learn the best way to modularize it?

sly grove
#

The question you need to ask yourself is "does this script have more than one responsibility?"

#

Is it handling just movement? Or is it also handling unrelated things like sounds, animation, etc?

pliant belfry
#

but i really think that something could be modular.

#

the problem is that i wanna see big games examples.

#

and it is rare.

untold moth
untold moth
compact ingot
# pliant belfry Hi, guys! I have a player controller with more than 2,000 lines. Can anyone rec...

the design question you have to ask yourself is: "can i organise the code in such a way that the important logic (the main business the system is dealing with) is all close together and easily readable, i.e. not polluted by details" then "can i maybe layer the system in a way that the details are a library or engine of modular components that get conducted by a higher level controller, in turn keeping any high-level concerns externalized". A character controller is usually a mess of different concerns (animation, gameplay, physics, audio, debugging, testing, automation, different modes etc.)... a "good" controller would make maintenance of these different concerns easy, such that changes limit the potential for bugs and other issues. When every concern is mixed in with all others, it becomes very difficult to understand what changes are safe and which ones can cause problems. When methods make assumptions about state that is not passed into it as an argument, or when it doesn't work for all possible argument combinations, the code becomes "hard to maintain". The bigger a project gets, the more formal the APIs get, as a way to help with making the assumptions/guarantees about whats going on explicit.

dusty wigeon
dusty wigeon
# pliant belfry intresting.

Single Responsibility Principle is really a good one. Unfortunately it is sometimes hard to understand/put it in practice correctly. However, if you search for the SOLID+T(Tell Don't Ask) principle you should find an array of example on how to concretely implements it.

pliant belfry
pliant belfry
#

More than 30 atributes.

untold moth
pliant belfry
untold moth
# pliant belfry A lot of handlers and all called.

The solution to this is to break it down into smaller "components(not necessarily unity components). State machine pattern could be used as well to isolate different states.
You character controller shouldn't handle everything, like camera, equipment, sound, cheats

pliant belfry
untold moth
#

Group parameters/properties into structs or class, instead of having a lot of primitive fields.

pliant belfry
untold moth
#

There's a lot of theory, but it takes experience to know how to apply it. Maybe start by looking at the OOP principles and SOLID principles

pliant belfry
untold moth
#

You can google the specific patterns as well. There are plenty of resources on finite state machine pattern.

compact ingot
# pliant belfry One of the reasons for seeking modularization was to reuse logic in NPCs, Monste...

the key is to not loose sight of what problem you actually want to solve, the immediate one of player value and the implied ones of the developer. All the principles that get thrown around, code features and patterns are ultimately only ideas that you have to put in service of something, in themselves they do nothing an achieve nothing. You may want to have a quick read of this book: https://www.amazon.com/dp/173210221X

pliant belfry
lofty falcon
# lofty falcon Do native to managed callbacks have to reference static delegates? The Unity Ed...

So I think I figured out what the problem was in case anyone is curious or searches in the future. I wasn't storing the callback as a part of the class instance so I think it was getting garbage collected. I don't think I saw this behavior in my console app because garbage collection probably wasn't triggering.

So for example, I was doing this which was crashing the unity editor:

public class MyClass
{
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate void NativeDefaultDeviceDelegate(
        IntPtr deviceId,
        IntPtr friendlyName,
        uint role
    );

    [DllImport("TestNative")]
    private static extern void Initialize(NativeDefaultDeviceDelegate defaultChanged);

    public void Initialize()
    {
        Initialize(OnDefaultDeviceChanged);
    }

    private void OnDefaultDeviceChanged(IntPtr deviceIdPtr, IntPtr friendlyNamePtr, uint role)
    {
    }
}

It needed to be changed to this to keep the delegate around:

public class MyClass
{
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate void NativeDefaultDeviceDelegate(
        IntPtr deviceId,
        IntPtr friendlyName,
        uint role
    );
    
    [DllImport("TestNative")]
    private static extern void Initialize(NativeDefaultDeviceDelegate defaultChanged);

    private readonly NativeDefaultDeviceDelegate _defaultDeviceChanged;

    public MyClass()
    {
        _defaultDeviceChanged = OnDefaultDeviceChanged;
    }
    public void Initialize()
    {
        Initialize(_defaultDeviceChanged);
    }

    private void OnDefaultDeviceChanged(IntPtr deviceIdPtr, IntPtr friendlyNamePtr, uint role)
    {
    }
}
frigid phoenix
#

how would one achieve this sort of camera shifting like they have in diablo 2?

So i want to open a menu and then have the camera still follow and look at my character, and rotate around them... but everything should be shifted to the side.

#

im using cinemachine

sly grove
#

or just a single unity camera and an overlay ui that animates alongside the camera viewport changing

sly grove
#

on which part

regal lava
#

Could make it lerp nicely with two virtual cameras

frigid phoenix
#

What you would do with the viewport

regal lava
#

but diablo is kinda instant

sly grove
frigid phoenix
sly grove
#

CM cameras don't define viewports AFAIK

regal lava
#

I'd probably not touch the viewport rect as the UI is obscuring it anyway

frigid phoenix
#

I'm using CM

#

And can't really get rid of it, too much intertwining

sly grove
#

changing the viewport rect is what lets you "shift" the image over

frigid phoenix
#

I see

sly grove
#

it's just not relevant to this problem

#

imo

frigid phoenix
#

Okay but basically I need to fiddle with the viewport rect

sly grove
#

yes

frigid phoenix
#

Thanks

regal lava
#

yeah viewport rect or just have a virtual offset

frigid phoenix
#

I was looking for the "thing" that's needs to change so I know what to lookup

#

Thank you both 🙏

#

My game is in my bio if you're interested 😁

frigid phoenix
#

_transporter.m_ScreenX = offset;

#

this is what i needed, thanks you both.

dusty wigeon
lilac burrow
violet valve
#

Can you ensure the chunks are loaded before creating the plants? That's not much of an answer, I know.

slate spoke
#

that's why there's a delay

slate spoke
#

lemme try changing those and see if that affects anything

#

oof, it didn't

#

also changing their initialization coordinates doesn't seem to change anything either

jaunty compass
snow trail
#

Hello, I have a question.

In Unity, an Animator is instanced. How do I make so that Animator is not instanced (having exactly the same variables)? I have exactly 2 same rigs, and I want them to play the same animation, but I don't want to put script inside the second rig.

In Unreal Engine, the AnimBP is shared in the character blueprint (if we have 2 rigs using same AnimBP, the variables would share).

dreamy basin
snow trail
winter nymph
#

Hey guys, I was wondering if anyone who has lots of experience in the saving data realm of coding.

I wanted to create a world like Kyora but I'm struggling on how to save the data of each pixel.

I find I have to store the pixels world coordinate and ID for what kind of material it is (stone, dirt, sand, etc. ). I found that would take a lot of bytes even with lossless compresion.

Than I see a world like this and I just end up wondering how in the hell is all that being saved.

EXPERT GUIDANCE NEEDED!

~It would be awesome if someone cant point me in the right direction of instuction on how to achieve this or towards someone who can further assist me.~

sly grove
#

I have to store the pixels world coordinate and ID for what kind of material it is
You don't have to store the world coordinate

#

that's an intrinsic part of its position in the array

untold moth
#

Games with procedural terrain generation, like Minecraft, terraria( and probably the game you shared), usually only save the seed that was used for the procedural generation and delta changes(if the world can be modified by the player). Then when the game loads it regenerates the world from the seed and applies the delta changes.

winter nymph
sly grove
#

doesn't minecraft save the whjole world after generation?

sly grove
#

so i answered

#

it's not that important of a distinction though

#

either way it's just data

untold moth
winter nymph
#

like run an a function to interpret its position in the long list of saved data. sorta like find out its position by its index?

sly grove
#

but I thought it stores all generated chunks in full

#

anyway either approach is valid

sly grove
#

the position IS the index

winter nymph
#

in the 3d bitmap you mean?

sly grove
#

In whatever array the data is being stored in

winter nymph
#

so would i just use a bitmap for something like Kyora

scenic forge
#

IIRC Minecraft does store generated chunks in full, because generation can change from version to version.

sly grove
exotic trout
#

and to reduce the processing effort needed to re-gen them

#

my current modded world is 2.86gb

#

the region data is 2.3gb of that

untold moth
#

You probably wouldn't want to save the whole map even with a bitmap. If it's just 1 million pixels/tiles in width and height, and you use 1 int per tile, it's already gonna be like 4 GB of data if my calculation are correct.

sly grove
#

you store generated chunks like minecraft does.

But also you wouldn't use a whole int per tile

#

unless you need 4 billion tile types

untold moth
#

I was assuming a bit mask, so that different info about the tile could be stored

#

But yeah, it could be less

sly grove
#

also you can compress the data, and store groups of chunks in different files

exotic trout
#

you could probably save data in semi batches right? eg. if

[x10,y10] to [x20,y20] consists of the exact same tile you don't need to save that info per cord, you could save that "batch" and re-build that knowledge at runtime?

sly grove
#

you'd probably just want to use off the shelf compression though unless you know something special about your data.

scenic forge
#

Compression algorithms handle repeating values extremely well.

exotic trout
#

Depending on preferred storage to processing ratio you could also maybe track if the given chunk has been modified compared to it's original seed generated version and if it hasn't just don't save it?

sly grove
#

yes, you could , but that has issues

#

like your procgen code cannot change from version to version

#

or the world changes

exotic trout
#

Forsure, depends on what they want. (i could personally actually see that is a possible benefit depending on how its handled)

scenic forge
#

General purposed compression algorithms in theory perform worse than if you come up with your own specialized algorithm catered specifically towards your data, but there's a bunch of science in it that you are probably not going to do better. An alternative approach is to transform your data in a way that makes existing general purposed algorithm compress better, eg delta encoding, going z>x>y rather than x>y>z, etc.

midnight violet
novel plinth
slate spoke
scenic forge
novel plinth
novel wing
#

Is there a way to force a script recompile on a single ASMDEF that doesn't require a script change?

stuck plinth
novel wing
#

Can confirm that reimporting a script inside of the assembly does though, thanks!

fathom ore
#

I've tried looking into IPreprocessShaders but it seems you can only choose to strip variants, not force them to be included.

echo coral
# fathom ore

There was a bug in some unity versions with shader stripping and addressables (basically all variants were stripped) but probably not whats happening to you.

fathom ore
#

Yeah, I don't think so since nothing uses addressables in this build

slate spoke
#

How do you calculate a mesh's normals if you're iterating over the vertex list by row and column?

#

(assuming said mesh is just a flat grid)

hardy sentinel
#

form tris first. there's a rule that determines tri normal based on vertex order

slate spoke
#

I do have that already

#

I ask because I'm making procedural terrain, and I'm trying to do the thing where you smooth normals between tile edges

hardy sentinel
#

normal = Cross(v1 - v0, v2 - v0).normalized

#

aka tri.normal = Cross(tri.v1 - tri.v0, tri.v2 - tri.v0).normalized

#

for shared vertices just do normals[i] += ..^ when calculating normals, then normalize each entry again at the end

slate spoke
#

oh, so I need to iterate over the vertices twice?

hardy sentinel
#

no, not the vertices

#

you should go through each vertex ONCE to calculate tris (mesh.triangles)

#

then you should iterate through the triangles twice. One for normals[i] += triangles[i]...normalized;, and the other for normals[i] = normals[i].normalized;

#

there are more performant ways to ONLY normalize the shared vertices, if you find that slow. But on most use cases just iterating through each of the normals likely won't be too slow.

#

do a if (normals[i].squareMagnitude > 1) on the second loop if you wanna squeeze in some easy performance

slate spoke
#

Ah, gotcha. It's been super easy to confuse myself with how I'm writing this, since I'm calculating the normals for one mesh using another with extra "border" faces so the terrain tile seams don't stand out

#

For context, my mesh generation is based on this video
https://www.youtube.com/watch?v=64NblGkAabk

But I'm trying to apply the stuff in this video to the previous
https://www.youtube.com/watch?v=NpeYTcS7n-M

Generate a landscape through code!

Check out Skillshare! http://skl.sh/brackeys11

This video is based on this greatwritten tutorial by Catlike Coding:
https://bit.ly/2Qd1o1d

● Perlin Noise: https://youtu.be/bG0uEXV6aHQ

● More on generating terrain: https://youtu.be/wbpMiKiSKm8

● Singleton: http://wiki.unity3d.com/index.php/Singleton

❤️...

▶ Play video

Welcome to this series on procedural landmass generation. In this episode we go on a long journey to fix a tiny problem with the mesh normals.

The full source code for this episode can be found here:
https://github.com/SebLague/Procedural-Landmass-Generation

If you'd like to support these videos, I have a Patreon page over here: https://www.p...

▶ Play video
#

and it seems like their approaches to iterating over vertices and tris are very different

hardy sentinel
#

cool!

slate spoke
#

I can't seem to get that working

#

This is what I came up with

        // normals first pass
        List<Vector3> normalsBordered = new List<Vector3>(vertexCountBordered);
        for (int i = 0; i < vertexCountBordered; i++)
        {
            normalsBordered.Add(Vector3.zero);
        }
        for (int vertBordered = 0, trisBordered = 0, z = -1; z < zSegments + 1; z++)
        {
            for (int x = -1; x < xSegments + 1; x++)
            {
                int vertex00 = vertBordered + 0;
                int vertex01 = vertBordered + xSegments + 1;
                int vertex10 = vertBordered + 1;
                int vertex11 = vertBordered + xSegments + 2;

                Vector3 normal000111 = Vector3.Cross(
                    verticesBordered[vertex01] - verticesBordered[vertex00],
                    verticesBordered[vertex11] - verticesBordered[vertex00]
                ).normalized;
                Vector3 normal001011 = Vector3.Cross(
                    verticesBordered[vertex11] - verticesBordered[vertex00],
                    verticesBordered[vertex10] - verticesBordered[vertex00]
                ).normalized;

                normalsBordered[vertBordered + 0] += normal000111;
                normalsBordered[vertBordered + 1] += normal000111;
                normalsBordered[vertBordered + 2] += normal000111;
                normalsBordered[vertBordered + 3] += normal001011;
                normalsBordered[vertBordered + 4] += normal001011;
                normalsBordered[vertBordered + 5] += normal001011;

                vertBordered++;
                trisBordered += 6;
            }
            vertBordered++;
        }

        // normals second pass
        for (int vert = 0, vertBordered = 0, tris = 0, trisBordered = 0, z = -1; z < zSegments + 1; z++)
        {
            for (int x = -1; x < xSegments + 1; x++)
            {
                normalsBordered[vertBordered + 0] = normalsBordered[vertBordered + 0].normalized;
                normalsBordered[vertBordered + 1] = normalsBordered[vertBordered + 1].normalized;
                normalsBordered[vertBordered + 2] = normalsBordered[vertBordered + 2].normalized;
                normalsBordered[vertBordered + 3] = normalsBordered[vertBordered + 3].normalized;
                normalsBordered[vertBordered + 4] = normalsBordered[vertBordered + 4].normalized;
                normalsBordered[vertBordered + 5] = normalsBordered[vertBordered + 5].normalized;

                if ((x >= 0 && x < xSegments) && (z >= 0 && z < zSegments))
                {
                    draft.normals[vert + 0] = normalsBordered[vertBordered + 0];
                    draft.normals[vert + 1] = normalsBordered[vertBordered + 1];
                    draft.normals[vert + 2] = normalsBordered[vertBordered + 2];
                    draft.normals[vert + 3] = normalsBordered[vertBordered + 3];
                    draft.normals[vert + 4] = normalsBordered[vertBordered + 4];
                    draft.normals[vert + 5] = normalsBordered[vertBordered + 5];
                    vert++;
                    tris += 6;
                }
                vertBordered++;
                trisBordered += 6;
            }
            if (z >= 0 && z < zSegments)
                vert++;

            vertBordered++;
        }```
#

and here's what I'm getting currently lol

hardy sentinel
#

also, why does your code look so confusing xD

slate spoke
# hardy sentinel what's with the draft lol

all of this is is a modification of the stuff in this third video lol
https://www.youtube.com/watch?v=f9uueg_AUZs

Download Link: https://drive.google.com/open?id=1B_IwrJKX9sQishwyrUbmWYCZrmhUwJTb

The project is using Unity 2017.3.0. Just FYI.


Update: Unity 2017.2.0 introduced the Vector2Int class. It doesn't make a difference, but it makes more sense to use it to keep track of tiles. It didn't exist when I originally made it...

▶ Play video
hardy sentinel
#

the outer loop ends with vertBordered++? wut

slate spoke
#

it's equivalent to "vert" in Brackey's video, it's just to indicate that it's for the vertices of the bordered mesh

#

the bordered mesh being the one the normals are calculated from

hardy sentinel
#

can you show your mesh generation code?

slate spoke
#

Should I send the file or is there a site I should use to share it?

hardy sentinel
slate spoke
#

uh, is that right?

hardy sentinel
#

whole thing should be simple after you get the vertices, and should be writeable like this:

Vector3[] vertices = GetVertices(...);
int[] triangles = GetTriangles(vertices);
Vector3[] normals = GetNormals(triangles);
slate spoke
echo coral
#

!code

thorn flintBOT
hardy sentinel
#

oh wow

#

I'm old

echo coral
#

use the recommended sites not whatever gdl space is

#

didnt haste bin go all shitty too

hardy sentinel
#

gdl.space was a hosting site hosted by Game Dev League -- the main Unity Discord Server before this server got every single unity user lol

slate spoke
hardy sentinel
#

and hatebin was the good hastebin

slate spoke
#

most of the functions at the bottom of the script are unused

#

all but GetHeight

hardy sentinel
# hardy sentinel whole thing should be simple after you get the vertices, and should be writeable...
Vector3[] GetNormals(int[] triangles, Vector3[] vertices) {
    Vector3[] normals = new Vector3[vertices.Length];

    for (int i = 0; i < triangles.Length; i += 3) {
        var (i0, i1, i2) = (triangles[i + 0], triangles[i + 1], triangles[i + 2]);
        var (v0, v1, v2) = (vertices[i0], vertices[i1], vertices[i2]);
        var (e1, e2) = (v1 - v0, v2 - v0);

        var normal = Vector3.Cross(e1, e2).normalized;
        for (int j = 0; j < 3; j++) { normals[i + j] += normal; } // 0, 1, 2
    }

    for (int i = 0; i < normals.Length; i++) {
        if (normals[i].sqrMagnitude > 1) { normals[i] = normals[i].normalized; }
    }

    return normals;
}
slate spoke
#

won't lie to you, I didn't even know you could do var (i0, i1, i2)

hardy sentinel
slate spoke
#

but yeah I'll break up the function a bit

slate spoke
#

it's just calculating the normals for a mesh and applying it to said mesh

hardy sentinel
#

that should be all it should be doing 😄

slate spoke
#

But what I'm doing is calculating the normals of a mesh using a different version of the mesh with extra vertices around the edge

hardy sentinel
#

no no, that's not the GetNormals's job.. if you want a different mesh, make the different mesh have the correct set of triangles 😛

slate spoke
#

..dude

#

watch this video please

#

or at least skip to the part where they explain how normal calculation works

#

for terrain tiles

hardy sentinel
#

I have watched this video in the past pretty sure. What about it?

#

he has the exact same code (in different style)

slate spoke
#

start at 6:48

hardy sentinel
slate spoke
#

his method labels the vertices unused in the final mesh as negative values

#

which doesn't apply to my method, where there isn't a difference between how border vertices and non-border vertices are calculated

#

the only way you can tell that a vertex is a border vertex in the context of my implementation is by going through it the same way it was initially generated

#

If that's avoidable, that would be lovely, but this is what I managed to get working up to this point

hardy sentinel
#

ok just to clarify all you want is adjacent chunks to appear smoothly connected, right? Did I misunderstand?

slate spoke
#

yes

hardy sentinel
#

and to solve that, you created another mesh from what I understood

#

that copies the original meshes, and adds vertices between the seaming points

slate spoke
#

eh, sort of. It places vertices in the same positions where those vertices would be on adjacent terrain tile meshes

hardy sentinel
#

so basically to connect m1 + m2, you create a m3 that contains m1 + m2 + m12_border?

#

or just a new mesh representing the m12_border?

slate spoke
#

the mesh used to calculate the normals for m1 would be m1 + m12_border, since it's not using the entirity of the m2 mesh

hardy sentinel
#

gotcha. Then you seriously don't need any special handling for the normals other than what I said 😛

#

Did you try that and saw it didn't work for you?

#

reason is that if the triangles are set up correctly, the normals will also be calculated correctly without having to check the original mesh

slate spoke
#

That probably calculates it correctly for the bordered mesh, the problem is grabbing the correct normal values from that mesh to apply to the final mesh

hardy sentinel
#

yes yes it'll all be correct! Since you copy the tris from the original mesh anyway -- the normals are also copied

slate spoke
#

sort of

hardy sentinel
#

basically normals are only cached as an optimization. In almost every single case they can be inferred by the vertex position of each triangle

slate spoke
#

it's not "copied" necessarily, the two meshes are made at the same time with different indexes

#

because as far as I know, I shouldn't be trying to use negative indexes in a list

hardy sentinel
#

just go ahead and try the normal calculation code xD just copy paste the code in

#

SebLag is indeed using negative vertex indices I suppose for smaller list size and cleaner code

#

since your mesh's vertices list already contains the border vertices (assuming), you haven't done anything wrong

slate spoke
#

draft.vertices only contains the vertices of the final mesh

#

verticesBordered is what has the vertices used to calculate normals

#

also I need to edit your function to make it use lists instead of arrays

hardy sentinel
#

actually.. what if you just do mesh.RecalculateNormals();? Does it make it look jagged?

slate spoke
#

I don't think I can while it's still a draft

hardy sentinel
#

yeah just apply it as draft I think and try (?)

#

without normals calculation

slate spoke
#

the function only returns the draft of the final mesh

#

so I wouldn't be able to do any calculations relating to borders

#

I changed your function to this

    List<Vector3> GetNormals(List<int> triangles, List<Vector3> vertices)
    {
        List<Vector3> normals = new List<Vector3>(vertices.Count);

        for (int i = 0; i < triangles.Count; i += 3)
        {
            var (i0, i1, i2) = (triangles[i + 0], triangles[i + 1], triangles[i + 2]);
            var (v0, v1, v2) = (vertices[i0], vertices[i1], vertices[i2]);
            var (e1, e2) = (v1 - v0, v2 - v0);

            var normal = Vector3.Cross(e1, e2).normalized;
            for (int j = 0; j < 3; j++) { normals[i + j] += normal; } // 0, 1, 2
        }

        for (int i = 0; i < normals.Count; i++)
        {
            if (normals[i].sqrMagnitude > 1) { normals[i] = normals[i].normalized; }
        }

        return normals;
    }```
#

"index out of range"

#

at for (int j = 0; j < 3; j++) { normals[i + j] += normal; } // 0, 1, 2

#

likely because the number of vertices != the number of triangles

#

because they're connected faces

hardy sentinel
#

oops yeah use triangles.Count when initializing the normals list

#

wait.....

#
for (int j = 0; j < 3; j++) { normals[i0 + j] += normal; } 
slate spoke
#

yeah I was about to say, how do we apply that to the final mesh then

hardy sentinel
#

vertices.Count was correct

slate spoke
#

that's.. not what it should be

#

it's actually not responding to light at all now it seems

#

ah I just had the function commented out

hardy sentinel
#

hmm can u ditch the if (normals[i].sqrMagnitude > 1) { part?

#

oh 😄

slate spoke
#

it's doing the same thing though

#

the error from before, I mean

hardy sentinel
#

can u show a pic of the issue?

slate spoke
#

it doesn't generate when it errors

hardy sentinel
#

with this?

    List<Vector3> GetNormals(List<int> triangles, List<Vector3> vertices)
    {
        List<Vector3> normals = new List<Vector3>(vertices.Count);

        for (int i = 0; i < triangles.Count; i += 3)
        {
            var (i0, i1, i2) = (triangles[i + 0], triangles[i + 1], triangles[i + 2]);
            var (v0, v1, v2) = (vertices[i0], vertices[i1], vertices[i2]);
            var (e1, e2) = (v1 - v0, v2 - v0);

            var normal = Vector3.Cross(e1, e2).normalized;
            for (int j = 0; j < 3; j++) { normals[i0 + j] += normal; } // 0, 1, 2
        }

        for (int i = 0; i < normals.Count; i++)
        {
            if (normals[i].sqrMagnitude > 1) { normals[i] = normals[i].normalized; }
        }

        return normals;
    }
#

like, with i0 + j

#

oh wait alright I see the issue

#

just swap the for loop with manual += on normals[i0], [i1], [i2]

slate spoke
#
    List<Vector3> GetNormals(List<int> triangles, List<Vector3> vertices)
    {
        List<Vector3> normals = new List<Vector3>(vertices.Count);

        for (int i = 0; i < triangles.Count; i += 3)
        {
            var (i0, i1, i2) = (triangles[i + 0], triangles[i + 1], triangles[i + 2]);
            var (v0, v1, v2) = (vertices[i0], vertices[i1], vertices[i2]);
            var (e1, e2) = (v1 - v0, v2 - v0);

            var normal = Vector3.Cross(e1, e2).normalized;
            //for (int j = 0; j < 3; j++) { normals[i0 + j] += normal; } // 0, 1, 2
            normals[i0 + 0] += normal;
            normals[i0 + 1] += normal;
            normals[i0 + 2] += normal;
        }

        for (int i = 0; i < normals.Count; i++)
        {
            if (normals[i].sqrMagnitude > 1) { normals[i] = normals[i].normalized; }
        }

        return normals;
    }```
#

index out of range at normals[i0 + 0] += normal;

hardy sentinel
#

wait

#

also, your normals can't be a list

slate spoke
#

it has to be

#

lol

hardy sentinel
#
    List<Vector3> GetNormals(List<int> triangles, List<Vector3> vertices)
    {
        Vector3[] normals = new Vector3[vertices.Count];

        for (int i = 0; i < triangles.Count; i += 3)
        {
            var (i0, i1, i2) = (triangles[i + 0], triangles[i + 1], triangles[i + 2]);
            var (v0, v1, v2) = (vertices[i0], vertices[i1], vertices[i2]);
            var (e1, e2) = (v1 - v0, v2 - v0);

            var normal = Vector3.Cross(e1, e2).normalized;
            normals[i0] += normal;
            normals[i1] += normal;
            normals[i2] += normal;
        }

        for (int i = 0; i < normals.Count; i++)
        {
            normals[i] = normals[i].normalized;
        }

        return normals.ToList();
    }
#

or

List<Vector3> normals = new List<Vector3>();
for (int i = 0; i < vertices.Count; i++) { normals.Add(Vector3.zero); }

...

return normals;
slate spoke
#

it should also be clarified, the only reason why these values are successfully being applied to the final mesh is because I'm still using the second pass from my original code

hardy sentinel
slate spoke
#

What I was trying to say earlier was that you can't just slap the normals from the bordered mesh onto the final because they're different sizes and have different indexes

#

yeah

hardy sentinel
#

I was kinda planning you would do GetNormals with draft.triangles and draft.vertices lol

slate spoke
#

ah, that likely wouldn't work either

#

both the bordered mesh and final mesh are generated starting from one corner and going row by row, the issue is that the border becomes the starting point of the bordered mesh

#

that's why I have both a vert and vertBordered

#

because their indexes are different

hardy sentinel
#
        ...
            if (z >= 0 && z < zSegments)
                vert++;
        }


        // uvs
        for (int i = 0, z = 0; z <= xSegments; z++)
        {
            for (int x = 0; x <= zSegments; x++)
            {
                draft.uv[i] = new Vector2((float)x / xSegments, (float)z / zSegments);
                i++;
            }
        }

        draft.normals = GetNormals(draft.triangles, draft.vertices);
        return draft;
#

although I admitedly still can't really understand why it's two separate meshes being created at the same time

slate spoke
#

so that I don't have to double the amount of for loops in my function lol

#

I'd be doing the same calculations twice for two meshes that are identical in shape besides the additional faces from the border

#

This does need to be as performant as I can get it

#

it's gonna be running on the Meta Quest 3 lol

hardy sentinel
#

oh, oof

#

maybe try making it work first before optimizing 😛

#

unless you can 100% understand what's going on in your code

#

because I'm struggling (it's 3AM tho :p)

slate spoke
#

Is there any better way that I can keep track of which vertices of the bordered mesh belong to the original mesh without relying on their indexes?

#

because that's what my implementation tries to do, but what you're providing assumes that draft.vertices[17] = verticesBordered[17]

#

which is not true

hardy sentinel
slate spoke
#

sure, but it looks like that assumes I'm using negative indexes

hardy sentinel
#

I'm just suggesting you try using the GetNormals method after UVs calculation of your original code

slate spoke
#

ah I see

#

I'm guessing this'll have good normals except for borders

hardy sentinel
#

gotcha. I think the issue is the new mesh has few too many vertices.

#

trying to decypher the code to verify atm lol

slate spoke
#

it intentionally has more vertices

#

the extra vertices are the border vertices

hardy sentinel
#

it should have more triangles -- not vertices

slate spoke
#

wh

#

how would that make sense

hardy sentinel
#

using existing vertices of two meshes to form new triangles

slate spoke
#

oh, no this doesn't have any information directly from neighboring meshes

#

it only has the means to calculate where the vertices on that neighboring mesh are

hardy sentinel
#

I see.. but if you just place two adjacent meshes without modifications, do they have a sufficient offset between them? or

slate spoke
hardy sentinel
#

even without modifications?

slate spoke
#

okay so think about it like this

#

faces without connected edges form a hard edge between them

#

you put two separate meshes side-by-side and line them up perfectly, it's identical to if they were the same mesh without a connected edge between them

hardy sentinel
#

gotcha. so you seem to understand you need neighboring mesh info -- where exactly in your code does that happen? in GetHeight?

slate spoke
#

yes

hardy sentinel
#

yeah sorry I may indeed not be able to help you.. still can't understand why you calculate for two meshes here instead of just draft

slate spoke
#

okay so back to the hard edge thing

#

if you wanna get rid of a hard edge, you gotta connect the faces, right?

#

once you have them connected, you can calculate the normals again and it'll be seamless

#

the trick is that once you have those normals calculated, you don't need those neighboring faces anymore

#

so what my code is supposed to do is grab those normals which are calculated as if the mesh were attached to all of it's neighboring meshes, and slap them onto the mesh that isn't attached

#

this is explained in the video I sent earlier

#

I assume you skimmed through it given how quickly you sited the code in it

#

he uses this graphic to explain it

#

the white vertices are the ones that belong to the final mesh

#

the black vertices are the ones that only exist in the context of the normal calculation, which is done on a separate mesh that is identical except for having those extra vertices

hardy sentinel
#

yup I got that -- in your case they're part of the mesh, though (called draft)

#

were you planning on discarding those "extra" vertices somehow? If so I completely missed that.

slate spoke
#

one has the extra vertices, the other doesn't

hardy sentinel
#

last question (same question as before, actually)-- and you'll only retrieve the delta for the MeshRenderer? Or the whole draft?

#

(delta being just the black vertices + their neighbors)

#

because in case you'll be using the whole draft, might as well only calculate the draft, is my point

slate spoke
#

the black vertices are only used to calculate the normals of the white vertices on the edge, after that they're not needed

hardy sentinel
#

alright! Gotcha better now 😄

#

was just confused because in the code you posted you're doing this:

#

so assumed you were going for some kind of hack

slate spoke
#

ah, yeah that's only done after the draft is already completed. And to clarify, I didn't make that ToMesh() method, that's part of the asset that was modified to make this procedural terrain generation work at runtime

#

Procedural Toolkit is the one I think

hardy sentinel
#

I can't really watch this 😄

slate spoke
#

which has all of the code that what I've made is built on

#

oof

hardy sentinel
#

why are you returning draft though in your method, if you just want a copy of the original mesh with altered edge normals?

#

shouldn't you be instead generating a new mesh with the standard vertices but the normals on the edges kinda altered?

slate spoke
#

because this is a modified version of a pre-existing method included in the code from that video

#

maybe I should clarify as well, none of what I wrote directly works with any Mesh types

#

it's all done while it's still a draft

hardy sentinel
#

hm ok so you can use the GetNormals method to get the normals of the bordered vertices + tris, but the issue is with mapping them back to draft, which has different indices

slate spoke
#

exactly, yes

hardy sentinel
#

and SebLague's approach of using negative indices to filter them out didn't appeal to you :p

slate spoke
#

is it even possible for me to use negative indices?

hardy sentinel
#

yeah I can see it requiring a complete rewrite for it to happen

#

have you debugged it to check if there's a pattern you can count on regarding the triangle indices?

#

like, maybe first original tri index would be mesh.width, ending up at mesh.width * mesh.height

slate spoke
#

the only thing I have to go off with the way I'm currently doing it is the fact that I have control over how the vertices are indexed in the firstplace, trying to figure out which vertices are which by effectively reverse engineering itself

hardy sentinel
#

wanna try the non-performant version, see if it's otherwise sound? 😛

#
var bNormals = GetNormals(bTriangles, bVertices);
var dNormals = new int[dVertices.Count];
for (int i = 0; i < bNormals.Count; i++)
{
    var bVert = bVertices[i];
    if (!dVertices.Contains(bVert)) { continue; }

    var dIdx = dVertices.IndexOf(bVert);
    dNormals[dIdx] = bNormals[i];
}

draft.normals = dNormals.ToList();
return draft;
#

(sorry for the weird code style)

slate spoke
#

I'll give that a try after I finish eating, just got dinner

hardy sentinel
#

Also, to clarify the misunderstanding:

  • I was thinking draft is the FULL mesh including borders the whole time until 15 minutes ago 😅
slate spoke
#

Ooh I see lol. Yeah we gotta discard those borders cuz otherwise there'll be overlapping faces that'll z-fight

#

or whatever the term is

hardy sentinel
#

yeah exactly that's why I was thinking u wanted to hack it 😄

slate spoke
#

fair lol

hardy sentinel
#

*single mesh meaning you get to discard trianglesBordered and verticesBordered and heavily simplify the code

slate spoke
#

does the order of the triangles or vertices in the list not matter?

hardy sentinel
#

reason is vertex and triangle order shouldn't be relevant in this context. All you need is just the correct vert indices on the correct triangles

slate spoke
#

huh. I was under the assumption it did

hardy sentinel
#

but that can get way too technical for 4AM Lyr 😅

slate spoke
#

fair, it at least gives me some direction. I appreciate the help

hardy sentinel
#

was fun

upper comet
#

I have a quick question. I was looking through some of the mathf source code and I'm wondering how the hell this works. it's comparing a boolean to a number, originalTo, current, output are all numbers

(originalTo - current > 0.0F == output > originalTo)
#

are booleans represented as numbers?

#

where something like 0 == False would return as True?

untold moth
untold moth
#

Whoever wrote this is just a crazy person.

upper comet
#
// Gradually changes a value towards a desired goal over time.
        public static float SmoothDamp(float current, float target, ref float currentVelocity, float smoothTime, [uei.DefaultValue("Mathf.Infinity")]  float maxSpeed, [uei.DefaultValue("Time.deltaTime")]  float deltaTime)
        {
            // Based on Game Programming Gems 4 Chapter 1.10
            smoothTime = Mathf.Max(0.0001F, smoothTime);
            float omega = 2F / smoothTime;

            float x = omega * deltaTime;
            float exp = 1F / (1F + x + 0.48F * x * x + 0.235F * x * x * x);
            float change = current - target;
            float originalTo = target;

            // Clamp maximum speed
            float maxChange = maxSpeed * smoothTime;
            change = Mathf.Clamp(change, -maxChange, maxChange);
            target = current - change;

            float temp = (currentVelocity + omega * change) * deltaTime;
            currentVelocity = (currentVelocity - omega * temp) * exp;
            float output = target + (change + temp) * exp;

            // Prevent overshooting
            if (originalTo - current > 0.0F == output > originalTo)
            {
                output = originalTo;
                currentVelocity = (output - originalTo) / deltaTime;
            }

            return output;
        }
novel plinth
#

iirc this would end up being branchless in plain c# too var t = true ? 1 : 0
i dont think in unity tho 😅

echo coral
#

i have little faith in ancient mono

stuck plinth
#

assuming you're targeting IL2CPP, it does at least pass through a modern compiler in the end haha

echo coral
#

thats true, presuming the produced cpp isnt nasty. some of what it gens is basically unreadable

thorn acorn
violet valve
#

Hey, I need to delete some generated files in my project, but I'm not sure where Unity caches these. Does anyone know where they might exist relatively? I haven't been able to find them, even by searching for the *.g.cs files on disk on Windows.

hardy sentinel
violet valve
hardy sentinel
#

also double clicking the error should open them

#

👍

violet valve
violet valve
# hardy sentinel also double clicking the error should open them

This just lead me to whatever internal method was throwing the exception, unfortunately. The stack trace didn't help... It was obfuscated like that. I knew that the type in the generated file was referencing a type that didn't exist anymore and that very error was blocking recompilation that would fix it.

#

Eeessh, okay... my project is in a strange broken state because my custom assembly OmiAssembly needs the UnityEngine.InputSystem definition as a reference. Here's a screenshot of what I'm looking at:

Note the "Missing reference" in the inspector when I select this assemblydefinition object in the first image.

In the second image, you can see that I can only view the assembly definitions that I have created in my project and none of Unity's build-in ones. If I try to click on the crossed eye icon (to show hidden files - allegedly there are 50?), nothing happens. I cannot view package files.

#

The errors in the console are suggesting that UnityEngine.InputSystem cannot be linked as a using.

sly grove
#

You need to press the+ and add the input system assembly as a dependency

#

And remove the broken one with the -

violet valve
#

I'll restart Unity without entering Safe Mode to demonstrate, if you can wait a moment. @sly grove

#

Thanks for responding, btw.

#

When I expand the drawer for Assembly Definitions, I see these three options. These are the assembly definitions that are defined as assets in my project. There is a hidden files icon (the eye with a cross) that shows that there are hidden files that I can display, but clicking on that button does not change what files are available in the selection window. The button is responsive, but does not toggle over to showing the allegedly hidden files. @sly grove

#

Clicking one time on the + button here creates a new entry labeled (No possible reference). Here is also a view of what is in that dropdown.

#

@sly grove To make it clear where I'm specifically stuck.

violet valve
#

I am installing a new version of Unity Editor (6000.0.41f1). I don't really want to create a new project and reimport parts piecemeal, but I'm unsure how to unravel this problem where core Unity assemblies are unavailable in the editor to provide for my own dependencies.

jolly token
#

If you do just go to that folder in project window and drag drop?

violet valve
#

For context, "my code" is a separate assembly. I could try to get rid of custom assemblies and let everything be Assembly-CSharp... I'll try that.

jolly token
violet valve
#

I would love to find the assembly in Packages/ if that's what you're thinking. 😄

jolly token
#

asmdef is in packages if you do have it installed

violet valve
jolly token
#

Sure. If you are not seeing it I suspect some kind of installation problem

violet valve
#

This wasn't a problem before I had some generated code that I KNEW was looking for structs that got refactored out of existence. To solve that, I tried to delete the generated files *.g.cs in the Library folder. Then, my custom assemblies couldn't find their dependencies, and the UnityEditor wouldn't locate .asmdef in property drawers, so I got caught in this state. @jolly token

#

So now, my assemblies can't find Unity dependencies and compile, but Unity won't compile to reveal the dependencies that I need.

#

So the editor isn't allowing me to view the Packages/ dependencies in property drawers to possibly solve the problem.

#

But right now, it's doing a reimport, so I can't tell you exactly where I'm at.

#

If I need to, I'm mentally prepared to port over to a new project, but I would like to understand how to salvage this problem within the confines of Unity.

jolly token
#

Hmm yeah we'll see

violet valve
#

Still rebuilding the project.

twilit citrus
#

I have a problem with my multi-training. As you can see, when a ML-Agent touch the wall or the ball, the episode ends, giving a positive or a negative Reward. The only problem is that the if one AI ends his episode, ends the episode of all others. Please help me!

sly grove
#

One thing you can do is find a project with an asmdef with the input system ref and copy the yaml

exotic trout
violet valve
# sly grove I wonder if this is an Odin problem or something

Thanks! I’ve actually decided to restart this project and reintegrate stuff somewhat piecemeal. Half the game is legacy stuff that was getting converted over to entities, and a huge branch of stuff ought to be its own package, so it is sort of worth it.

#

Like, a lot of state automata are generic, but contain some stuff that should just be part of derived classes. Too many references to UnityEngine in places where the code isn’t really “Unity-side”, etc. It could use a pass.

modest solstice
#

anyone familiar here with burst? I'm looking to do some optimizations on my codebase and want to start integrating jobs in the future. However since I still haven't fully wrapped my head around it I'm just starting simple by going through my code and restructuring things to utilize burst whenever possible

#

with that I have a couple of questions about [BurstCompile]

#

are there any benifits to using [BurstCompile] on a struct? from what I've read there is

#

and in addition, when using [BurstCompile] on the parent struct, any sub methods within the struct (i.e. static methods) do they automatically get flagged with [BurstCompile] or do I have to add it manually?

echo coral
#

The whole struct should get burst compiled. You would know if it didn't work if the job cannot compile or execute.

modest solstice
#

the struct is not being used in a job currently, I'm also wondering if using that tag also has benifits performance wise?

#

like I mentioned I read online from sources that there is, but not too sure

echo coral
#

You can have a job in normal managed c# or choose to use burst with it which will compile it to native code to then execute.
When you use burst you are limited in what you can use and often need to use native collections to put data in and get data out

untold moth
# modest solstice are there any benifits to using [BurstCompile] on a struct? from what I've read ...

Burst compiler just compiles the code using certain CPU features, like SIMD, so not any kind of code could benefit from it. It's mainly useful for vector math, where many variables(vector components) get processed in a single CPU operation. Possibly loops with arrays are simd optimized as well if there are certain math operations performed. There are some other features too, but you should research it yourself.

#

You can try it out, test and profile with/without to see if it provides any difference in your specific case.

#

Using it on a struct would just mark the methods of the struct to be burst compiled, just like you said. I think it applies to static methods too. You should check the docs to make sure.

dire totem
#

Anyone know how Unity's build system works?
I'm trying to get a source generator packaged with a nuget package to work - so the package comes with a .dll library and a .dll source generator.
When writing scripts, I can reference stuff in the .dll library fine, but when the generated code from the source generator isn't able to.

#

I've checked the unity logs and there aren't any warnings

novel plinth
exotic trout
novel plinth
#

that said, y'all better learn how to bitshift starting from now 😉 ... bitshifting is king when it comes to simd

#

Fun fact, System.Numerics types been SIMD'd since ancient times including their Vector2/3/4 and Matrices

dire totem
#

And TensorPrimitives makes it super easy to write fast hardware accelerated code in some cases

novel plinth
dire totem
#

can’t wait

novel plinth
# exotic trout Just out of curiosity could you elaborate on those examples? New to the subject ...

missed the example part, but the code would look like this

var xyzx_a = Vector128.Shuffle(a, Vector128.Create(0, 1, 2, 0)) ^ neg;
var dat = Fma.MultiplySubtract(yzxz_1, zxyz_0, Fma.MultiplyAdd(val0, b, Fma.MultiplyAdd(val1, val2, val3 * val4)));

in this case I'm shuffling a 128 bit vector once, then XOR-ing , then do bunch of FMA3 instruction mm_fmadds Multiply + Add (Fused operations). Those 6 operations will just be 3 instructions in this case and 1 rounding, due to it's fuse nature of FMA3 instruction

#

ignore the janky naming scheme there, straight up copied/pasted from my code 😌

dire totem
#

gotta be careful with shuffle tho

novel plinth
#

nah, the regular Shuffle is not the same with ShuffleNative... the Native version is unsafe operation, the regular Shuffle is pretty much safe

digital sand
#

Hey, how do I check if a Component I have referenced earlier still exists or if its GameObject has been deleted from the scene?

#

Is this related to the garbace collector (do I need to interact with it to figure that out)?

lilac burrow
digital sand
tall ferry
tall ferry
slow jay
#

i'm downloading a .txt file at run-time and I don't know the encoding used. I wanna get it into utf8. Is there some simple method I can use to convert from aribtrary encoding into utf8? or do i have to write it myself.

#

like because it needs to handle utf16-le, utf16-be, ascii, etc.

echo coral
#

System.Text.Encoding.UTF8.GetString can be used for example

sly grove
slow jay
#

but in case it changes

sly grove
#

why would it change

#

Are you not responsible for these files?

echo coral
#

oh well if endianness is different then you need to double check but most platforms now are little so it can probably be ignored

azure meadow
#

What would be the adviced way to get LUA into unity 6?
Moonsharp? Is there something newer/better? Any insights?

#

It seems most lua assets on the store are just moonsharp wrappers

sly grove
hardy sentinel
#

Can you guys share some reasons for bringing in LUA to a project?

sly grove
hardy sentinel
untold moth
#

You can also hire a bunch of Roblox devs/players for "cents", instead of actual C# developers.thinksmart

exotic trout
#

I know it’s a joke but Roblox devs are actual developers too

untold moth
#

No need to repeat my joke.😛

#

Maybe they're developers on the level of game modders. Though, some modders(Skyrim fo example) mess with things on a deeper level than actual game developers(like code injection and rendering pipeline modifications)

hardy sentinel
#

Well I know some very talented devs that do games with Roblox from time to time

#

I’ve never seen any actually publish a game tho — I heard them rant about silly restrictions like physics etc.

exotic trout
novel plinth
eternal token
#

Weird question, but is it possible to give an object "FPS Priority". Imagine a scenario where a bunch of physics simulations fluctuate around 60 fps, but there is a bouncing ball that I want to see at 100 fps, even if that means that the other objects dip to 55 fps. Weird question, I know.

echo coral
stuck plinth
eternal token
#

Oh that is interesting.

#

So I could detect that the deltaTime on the ball is getting too high and adjust the simulation rate of other objects.

#

I'm not actually trying to make a ball bounce but that's the easiest way to explain it.

echo coral
#

oh dang i totally forgot about this, you could just use this to always simulate important objects more frequently

#

or others less

lament salmon
#

Are you sure you dont just want interpolation?

#

Do you actually need it to simulate more often or just to look smoother?

#

I don't think that two physics scenes can interact with each other

eternal token
#

It's complicated and very much in the idea state. The scenes not being able to interact wouldn't be a problem.

mighty shore
#

So it turns out when uou do multi-threading, if another thread is allocating lots of memory, that another thread can slow down other threads though they are not connected in any way. It happens because stuff happens at IO level?

#

can someone confirm this behaviour? that it is actually the case?

echo coral
#

could be due to memory allocation on one thread blocking another? or some large gc run? tbh im not sure 🤔

flint sage
#

How are you multi threading

mighty shore
#

the main thread has

dictionary

main thread is mono behaviour and doesnt do anything with the dictionary

the 2nd thread runs and allocates and adds lots of stuff to the dictionary

echo coral
#

did you pre allocate the dictionary size? are you making lots of garbage as you do this?

flint sage
#

Is this an actual thread or something like a task

novel plinth
#

virtual thread?

flint sage
#

C# doesn't currently have virtual threads, I got confused

lament salmon
mighty shore
mighty shore
flint sage
#

What and how are you generated data

echo coral
#

if you are adding many thousands of elements then the dictionary will keep being re allocated to resize. so giving a smart initial size can help greatly.

mighty shore
#

the idea was that the 2nd thread would not interfear with mainthread(unity)

mighty shore
flint sage
#

Is this in editor?

mighty shore
#

no. it is ran during gameplay

flint sage
#

In editor?

#

I.e. not a build

mighty shore
#

it is in the editor and executed when u hit play

novel plinth
#

how you spawned the thread?
i'm confused here, you said tasks, or the good ole Thread?

mighty shore
#

actually I am abit confused between tasks and thread.

I launched a thread called Apple and then I created bunch of tasks inside the thread Apple

#

I just realized I don't know clear difference between tasks and thread

sly grove
mighty shore
#

When I create bunch of tasks, I dont specify which thread is going to run it.

when I create a thread I specify what code that thread is going to run

#

what is running my tasks?

flint sage
#

It depends

#

(not that say that there is never a thread)

#

If you do task.run, it generally spawns a thread (I think unless you have some weird scheduler it always spawns a thread)

mighty shore
#

First I am going to try to set initial dictionary size and see if it resolves my issue

#

second if it doesnt then... I dont know

#

lol

flint sage
#

You could always provide more info, rather than us having to pull everything out of you

echo coral
#

Task.Run and unity jobs should be using already created worker threads

mighty shore
echo coral
#

no

novel plinth
#

or just Span<T>... I personally prefer the latter

echo coral
#

i like me some stackalloc span sometimes

mighty shore
#
        for(int i = 0; i < bestNumThreads; i++){
            var threadIndex = i;
            tasks[i] = Task.Run(() => {
                //Allocate lots of memory
            });
        }
       // return;
Debug.Log($"Number of tasks: {tasks.Length}");
while(!tasks.All(t => t.IsCompleted)){
    // Wait for all tasks to complete
}```
#

I dont think the issue was dictionary

#

I removed the dictionary expanding section and just did lots of memroy allocation

#

The game still freezes-chokes up

novel plinth
#

ofcourse it allocates, as I pointed out above, arrays aint free

echo coral
#

your game freezes as you are looping till the tasks are done...

#

what did you expect

mighty shore
#

no that is secion of code inside a thread

novel plinth
#

those Task.Runs would most likely kill the perf more than you gain anything from it

mighty shore
#

not the main thread

#
    var tasks = new Task[bestNumThreads];
        for(int i = 0; i < bestNumThreads; i++){
            var threadIndex = i;
            tasks[i] = Task.Run(() => {
                //Allocate lots of memory
            });
        }
       // return;
Debug.Log($"Number of tasks: {tasks.Length}");
while(!tasks.All(t => t.IsCompleted)){
    // Wait for all tasks to complete
}
echo coral
#

Yea sometimes the cost of starting many tasks or threads out weighs the benefits

#

Perhaps 1 thread where you re use allocated memory would be better? can you share more of the work?

mighty shore
#

I think that's how I should do it

#

per task, just allocate one array, then re-use

#

right now I create LOTS of small arrays per task

echo coral
#

you can also look at the unity job system + burst + native collections

#

native collections are needed for burst but also mean no gc!

mighty shore
#

I think Unity's job system is really helpful that it provides framework that tells you how to use it. But I feel like all the structures of using Unity's job system adds too much work on my shoulders. Of course I wouldn't run into walls like this if I used Unity's job system. I think my issues happen due to my low understanding of inner workings of the computer system. I think if I were smart, I wouldn't have ran into the wall and just would have been fine multithreading myself without using unity's job system.

novel plinth
#

that said, I don't think you really understand the concept of multithreading here..

mighty shore
#

yeah I think my understanding of the multithreading is low

#

I do use ConcurrentDictionary and other concurrent stuff though

echo coral
#

concurrent collections are good when you may be reading and/or writing from the collection from multiple threads

#

e.g. block other thread till writing is safe, skip reading until its safe to do so on main thread (so we dont pause the main thread)

compact ingot
flint sage
mighty shore
#

I doubt it because, when I set the allocated array to be small, the problem goes away

#

I do allocate like [1000000] size of two ints worth of array for like 10x10x10 times

#

so that would be (64 bytes) * 1000000 * 1000 bytes

echo coral
novel plinth
# mighty shore right now I create LOTS of small arrays per task

Consider using ArrayPool<T> for those arrays, it's zero alloc 99.999% of the time if you return it back to the pool each time you're done with it.

also, what heavy operation that requires you to task.run in a tight loop like that?

I'm saying is that, if it can be done on the mainthread, ditch out those task.runs and it will save you lotta headache

mighty shore
#

basically reading a map like in Minecraft, read map from disk, load it onto ram

#

I should re-use array (as buffer) or use ArrayPool. This seems like being clear the more I talk

#

I made a mistake. When I just need to read, I could have just reused the array 100%

novel plinth
mighty shore
#

The entire map I am reading is about size of
100100100 1010*10, so that woud ble 1,000,000,000 units multiplied by 64

#

64,000,000,000 bytes

flint sage
compact ingot
#

all the comments are just repetitions of the same ideas and advice

mighty shore
#

The issue is my stupidty of not reusing an array but instead creating arrays each time I need to read, I think, as pointed out I should use ArrayPool

echo coral
#

How about you try that out and report back?

compact ingot
mighty shore
#

That sounds great

mighty shore
#

we learn as we go

compact ingot
#

we learn to walk before we run though

mighty shore
#

maybe someone's way of learning to run is tumbling as they try to run

#

shrug

lament salmon
#

You have a point, some people learn more chaotically

mighty shore
#

I upvote this opinion

#

I don't want to sit and read through all the ins and outs of multithreading. I would like to build something and hit walls and burn.

#

anyway gona do the thing to fix my game and comeback to report

mighty shore
#

yes it works yeaeeee

#

no more choking to freeze

#

I can construct meshes almost immediately. But it looks like reading files is slow.
I guess I need to load file content to my ram ahead of time (during loading I guess?) instead reading it when I need to render a chunk

echo coral
#

still looks pretty slow. is this doing something like marching cubes?

#

but glad its better than before!

mighty shore
#

That's 500x500x500 cubes though, hmmmm

#

I do agree that it feels slow still

#

This is when I pre-loaded the world data onto memory instead reading it each time.

mighty shore
novel plinth
#

told ya 🍷

mighty shore
#

I probably need to really scale up work load if I wnated to take advantage of it

#

it seems like the bigger the amount of work, better it is

#

so I think I solved "loading issues"

#

rendering 500x500x500 voxel cubes take about 18 seconds

#

I feel like this is slow

novel plinth
#

make a bigger chunk instead

mighty shore
#

I am using 16x16x16 sub-chunk size, just like Minecraft

novel plinth
#

you can then further insteanced mesh them

mighty shore
#

but then when I edit one voxel, the bigger the size of chunk to be changed in rendering

#

also I feel like this rendering being slow is more of my fault than the design of it

#

16x16x16 subchunk rendering size is blazing fast in Minecraft

#

I must be doing something stupid to slow it down

novel plinth
#

if you want to keep it, make a bigger chunk as LOD

mighty shore
#

I can do that? chunks as LOD?

novel plinth
#

so at certain distance it wont kill the perf

novel plinth
#

or if you're lazy, just use instanced indirect and make their bounds be your culling distance

#

so no need for LOD this way

#

but I'd still prefer LOD tho, you'll have more control over it

#

and much simpler especially when they've fixed shape like a cube you showed

mighty shore
#

I don't understand this; so I know launching lots of thread can be rather inefficient than doing it with a single thread. Let's say I launch a thread. Then in that thread I launch 100 threads and 100 tasks of inefficient slow jobs. But these inefficient jobs should not slow down the main thread right? but the main thread (unity) slows down significantly.
I expect Unity(main thread) to run flawlessly because all the dirty works are being done in other threads. Main threads do not have any lock either.
I tested whether it is my system slwoing down by running some 3D games. The other 3D games run fine. So I think the threads launched are somehow still connected to main-thread. And this is driving me nut. How is this possible?

#

ohhhhhhhhh

#

could it be because the other thread is expanding list inside the Monobehaviour?

#

ohhhhhhhhhhh

#

If the thread is expanding the list(or dictionary) inside MonoBehaviour, the object needs to be reallocated for the new size

#

ohhhhhhhhhh!

exotic trout
#

A lot of multi-threading is fundementally limited in Unity because of how much has to circle back to unity's systems which are mostly single threaded

mighty shore
#

yes. I didn't know how the hell it was circling back

#

but as always, I was the problem, the human error

regal lava
#

which is why compute shader is superior

mighty shore
#

I mean compute shader being in the GPU makes it, by design, separated from the CPU. Which is cool I guess

regal lava
#

I reserve my CPU for physics and pathfinding calcs. Let the gpu do everything else

mighty shore
#

Right now I need to generate mesh for my Minecraft like world

#

do you think I could use compute shader to generate chunk shapes?

regal lava
#

pretty standard ye

mighty shore
#

I never heard using GPU to create verticies and send it back to CPU then I set the mesh with the GPU-generated vertices to send it to GPU

#

the process, I think, I can do it, but that sounds so odd

regal lava
#

Why do you need to send it back? Just do everything in the GPU

mighty shore
#

because I want triangles to feed to MeshRenderer?

#

r u suggesting I do that... what was it called... the method ahhh lettude method?

#

voxel lattice

#

I heard this is pretty inefficient

#

most folks I know that do voxel stuff, are against it

cold talon
#

I made a cool level editor system for my vr game with save and loading that detects if the player is in vr or emulating the apk on pc for the editor version, but when i try building it says handles and editorGUI dont exist in the context. Please help. I even tried wrapping to see if i could even get it to build even though the version wouldnt work in a emulator and only the editor but that still didnt work

#

wait chat i think i figured it out

#

i had it drawing gizmos in here for no reason

regal lava
# mighty shore because I want triangles to feed to MeshRenderer?

Was looking into my previous project I was working with this and yeah, I do all the iterating for chunking inside of the GPU, pass it back to the CPU to then use the Mesh API. I think it turned out to be a lot quicker than trying to thread it but I wasn't something I probably had correctly implemented.

mighty shore
#

nice

regal lava
#

trying to figure where I left off but editor tooling is my bane

mighty shore
#

btw

#

I am realizing even if I do mesh generation fast

#

I will prob run into fps issue

#

I wish Unity had Nanite like Unreal

#

this is so sad

#

I really like C# and Unity but I might need to move to Unreal

#

for this project only perhaps

#

Why does unity not have Nanite. It's been years. And I know that Chinese Unity already does Nanite stuff 😦

regal lava
#

Everyone creating their own voxel engine nowadays. Just do that np

mighty shore
#

yeah its the recent fashion

#

lol

strange blade
#

i have written a script that combines spriterenderers into a mesh, then creates a texture to place on the mesh based on my spriterenderers. Everything works fine in editor, but when i build my project, the texture looks all different.. Im not sure why the results would change in my build but work in the editor.

Any ideas?

long ivy
#

are any of your sprites in an atlas?

strange blade
#

no none of them are

mighty shore
#

What was taking 18 seconds is now done in almost 5 seconds!

#

Threading is best

mighty shore
#

I don't think this is what u r referring to? What is the "instanced indirect"?

#

this?

#

Renders multiple instances of a mesh using GPU instancing and rendering command arguments from commandBuffer.

#

ohhh so I could copy paste a cubes

mighty shore
#

they can do 1000+ render distance thanks to LOD

regal lava
#

lol how do you even LOD voxels

mighty shore
#

yeah it's a bit odd

regal lava
#

chunking is basically the LOD

mighty shore
#

I think the maximum LOD would be

#

16x16x16 chunk being rendered as a single cube

#

16x16x16x could be rendered using 8x8x8 voxel data

#

basically treat the chunk like an image file and resize it

regal lava
#

makes sense, would require maping the texture across it at that size

#

and would only work if all textures match

#

well, actually not exactly. UVs would be what changes the texture.... so yeah basically chunking

mighty shore
#

its odd

#

yeah

#

I need LOD so bad though

#

I originally ditched the idea of tiny voxels

#

but with LOD I think it is possible

mighty shore
#

It just came up to me if I do box sampling to 100^3 voxel cube it will be 96^3 (each box sampling will reduce edges) and so on and so on until it is 4^3 voxels cube size

cold abyss
#

is it possible to lock a cursor in its palce in unity?

mighty shore
#

yes

cold abyss
#

how?

mighty shore
#

google search

cold abyss
#

i did

#

but nothing

mighty shore
#

wait are you saying that you went to lock a cursor not in the center but where it is?

cold abyss
#

yes

mighty shore
#

you will need to lock the cursor in the center then render your custom cursor on the screen and when you want to lock it you do not move the custom cursor

cold abyss
#

but i dobnt have a custom cursor

mighty shore
#

custom cursor is just an image that you draw on screen

#

you just throw a circle in the paint application

#

use that as your cursor

cold abyss
#

but then the position of the main cursor will be in the middle of the screen

mighty shore
#

yes

cold abyss
#

yeah so then it wont be good

#

since if i set it back it would be annoying

mighty shore
#

does it have to be a real cursor? do you have a reason for it to be a real cursor?

sly grove
#

It's not really possible to lock the hardware cursor anywhere except the center.

cold abyss
#

yeah since i want em to like hold right click to orbit around the player

#

and then let go of it to stop

sly grove
#

You can get partway there with cursor warping, but Unity's framerate will always be slower than the mouse cursor hardware poll rate

mighty shore
#

why can't you just throw a fake cursor? if you draw a fake cursor that looks like a real cursor it's the same look

cold abyss
#

they needa fix that tbh

mighty shore
#

if you also implement the functionality of cursor to a fake cursor it's just going to be same as the real cursor

sly grove
cold abyss
#

how do you cursor warp?

mighty shore
mighty shore
#

but I can already imagine some complications that's related to Windows

#

I bet there is going to be complications when executed inside the scene and as a build

sly grove
cold abyss
#

alrighti ma see if it works

mighty shore
#

honestly I didn't know you could move cursors around

#

is this new? I don't think it existed before

sly grove
#

(which is like 5 years old)

mighty shore
#

I think I remember this. I think long ago I tried to use it and it was very glitchy. as I said it behave differently depending on where I was using it

sly grove
#

That's a 5 year old post.

mighty shore
#

yes I'm reading through the thread and I'm remembering I experiencing the same issue

#

I remember it was like weird when I used in scene, standalone, and Apple pc

sly grove
mighty shore
#

aha

torpid knot
#

Please help me. I need to rotate a rigidbody about an axis, like RotateAround but physically

torpid knot
#

The angular velocity rotates it about the pivot of the object.

sly grove
#

indeed

torpid knot
#

This is not what I need

sly grove
#

if you want your body to orbit a point, you need to basically do an orbital simulation

#

that would mean a constant force towards the center of the orbit

#

(like gravity)

#

as well as an initial tangential velocity

#

"rotate about an axis" implies rotating it e.g. with angularVelocity

torpid knot
#

uh, I think I just need to move the position in such a manner

#

In a way where I would be able to rotate the object into position