even if you ensured that the await occurs on the main thread using await UniTask.SwitchToMainThread(), this statement await ... will permit the main thread to do other work while it waits for the result of the task (i.e., the meaning of the keyword await). however, if this is a network stream, WriteAsync returns immediately or returns an error at the time it is called.
#archived-code-advanced
1 messages · Page 1 of 1 (latest)
i think everything else people are telling you is noise
and not relevant
or wrong
i am avoiding the use of the word blocking
it is a confusing word for a lot of people
hi, can someone explain to me how do fixedUpdate and Update run on the same thread ? how is this possible since they are 2 different parallel loops ?
since pistoleta is using unitask, there aren't any difficulties getting a task to run on the correct thread
if you need events, use UniRx
That's not the problem I was addressing with my post though
I'm talking about when you're waiting synchronously on an asynchronous operation
i still dont understand, wont the thread.sleep that keeps fixed update constant interact with update() and make it constant too if they were on same trhead ?
there is no thread.sleep in FixedUpdate
if you want to see the real player loop, you can step through PlayerLoop.GetCurrentPlayerLoop() in the debugger.
fixed update is an opportunity for game logic / business code to make changes to physics entities before the physics simulation is run. for example, to add velocity to a rigidbody using your own script code.
that is all it does
nothing more
the velocities, masses and positions are shipped off to physx, a library in the unity executable, which runs it all and gives it back to unity. unity decides whether or not to run another fixed update (and therefore physics timestep) if the rendering is so slow that you have not passed enough physics time relative to game time
@wet sail does that make sense?
fixed update receives an amount of time Time.fixedDeltaTime, but that is not the same as wall clock time
var scripts = FindAllObjectsOfType<MonoBehaviour>();
while (!EnoughPhysicsTimeHasPassed) {
var timeStep = CalculatePhysicsTimestep();
foreach (var monobehaviour in scripts) {
monobehaviour.FixedUpdate();
}
Physics.Simulate(timeStep);
}
foreach (var monobehaviour in scripts) {
monobehaviour.Update();
}
yeah but wont monobehaviour.FixedUpdate(); freeze the thread ?
before monobehaviour.Update(); is called ?
you've implemented fixed update
right?
like you've made a callback in a script called FixedUpdate
right?
have you ever done anything in a fixed update that "freezes the thread"?
i know but im talking about the unity internals
how did they make the fixed update loop ?
i updated my snippet to show you
fixedupdate doesn't do anything
Physics.Simulate does
you can even call physics.simulate
so basically fixed update is inside "update" ?
no
is update being called inside of fixed update in my example above?
it's for loops (hence the "loop" in player loop)
basically yes
if not then wouldnt the while delay the update() too ?
Update happens after FixedUpdate, so yes if FixedUpdate runs Update is delayed by it
it does, yes
you are correct
it delays it in wall clock time
i'm going to delete my last thing because it's only going to confuse you more
it delays it in terms of wall clock time. Time.deltaTime, Time.time... are illusions
Time is pretend, and your code can be fed any time value and the simulation can be advanced at any rate.
FixedUpdate is just a loop that occurs before update and advances fixed time, simulating as many steps as needed in that frame. If not enough time has passed to run a simulation it won't run. If lots of time has passed it can loop many times. Simulation doesn't actually occur when fixedTime equals time, it's just advanced at fixedDeltaTime and kept at the same pace as Update
alright im still confused a bit, one sec
alright so lets say this is our fixedUpdate
public void FixedUpdate(Action<float> Step)
{
int frameMilliseconds = _fpsCap < 0 ? 0 : 1000 / _fpsCap;
Stopwatch stopwatch = new Stopwatch();
int overTime = 0;
float delta = 0;
while (!_quit)
{
stopwatch.Restart();
delta = (frameMilliseconds + overTime) * 0.001f;
Step(delta);
stopwatch.Stop();
int stepTime = (int)stopwatch.ElapsedMilliseconds;
if (stepTime <= frameMilliseconds)
{
Thread.Sleep(frameMilliseconds - stepTime);
overTime = 0;
}
else
{
overTime = stepTime - frameMilliseconds;
}
}
}
where do update gets called then ??
lol
it will be called after all the fixed updates are called
exactly like in my example
i wrote the snippet verbatim!
you see where update is called
i made it even easier for you to read
your snippet says :
while // blocks thread for 60fps
update // called after the thread is blocked for 60fps
that's right
but thats not what happen
that is exactly what happens
update runs faster
how does update runs faster / slower ?
that's how, and the body of the while loop is skipped
so it sounds what you're really confused by is EnoughPhysicsTimeHasPassed
and CalculatePhysicsTimestep()
does that sound right?
no it's a bool
yeah i mean when its true ?
the documentation explains how it works
you don't want your physics simulation to be too far behind or too far ahead
if your physics has been evaluated up to 1.2s of game time, and you've finished 1s of game time, and your physics timestep is 0.2s, EnoughPhysicsTimeHasPassed will be true.
is that helpful?
sometimes, when starting a new frame, for the first time EnoughPhysicsTimeHasPassed is true, so fixed update is not called at all that frame
and physics is not simulated that frame
does that make sense?
the snippet i showed is executed every frame
it is exactly where i wrote it yes
but isnt update the frame loop ?
no
Update is a method
if you're asking what it is for real
it's a method that gets called in a loop at the "right time"
its purpose is to give you a chance to change transforms and other render-impacting code in an ergonomic way
so the delta of update isnt difference between 2 frames ?
FrameLoop = { Update + FixedUpdate } right ?
FrameLoop has a delta
itself
what you are calling FrameLoop consists of everything in the array PlayerLoop.GetDefaultPlayerLoop()
it should be clear to you what it's real name is 🙂
Update and FixedUpdate are callbacks
they are called by objects in the array returned in PlayerLoop.GetDefaultPlayerLoop()
listen i don't know why unity doesn't document this!
player loop didn't exist until recently
since 2015 or whenever they wrote that execution order thing
because reality is super confusing
everything that the document says is true
so i think i have answered your question
i think you are confused by "sometimes, when starting a new frame, for the first time EnoughPhysicsTimeHasPassed is true, so fixed update is not called at all that frame"
if you have advanced your physics simulation enough, you don't simulate physics
the consequence is fixedupdate is never called during a frame
that seems to be what you are hung up on
you also thought that making fixedupdate take longer means physics simulated for a longer timestep
it doesn't
Physics.Simulate(timestep) doesn't refer to a timestep in wall clock time
it refers to a time step in game logic time
is that helpful?
fixedupdate doesn't have anything to do with simulating physics
Physics.simulate is not called inside fixedupdate
so there's no physics simulation happening there, right?
you see in my snippet where it is called
what Stopwatch measures
the time written on the clock on your wall
alright
colloquially people call fixedupdate the "physics" but it's not
i got the physics simulation part
but there's still sth bothering me
what is deltaTime ?
is it playerLoop delta ?
what can i do. game developers also do not name period and frequency correctly
well if you would
look at the thing i've been telling you to
a bajillion times
you can see what all the loops are called
and there's something like that
Is it better to call EventSystem.current or find the event system with tag, assuming my scene only has one event system
it is an array with like 27 elements in it on HDRP
usually if you're directly referencing the eventsystem you are doing something wrong
Using it for SetSelectedGameObject
more or less yes. consider that if your game is in the background and is not rendering, wall clock time passes but Time.deltaTime will still give the right answer
so IRL the physics.Simulate isnt called at a fixed time right ? cuz what guarantees the PhysicsTimePassed that flags the EnoughPhysicsTimeHasPassed to be precise ?
however, that calculation doesn't get called every time you call Time.deltaTime
it is done before the calls to update
Time.deltaTime gets a float out of a field. it doesn't compute anything
hmm
i'm worried i just confused you more
can you tell me what your gameplay objective is?
no i got it
or how this relates to your application
it's just incrementing a float with other floats. it doesn't really use wall clock time
im trying to re-implement the Monobehavior methods for fun
As I said, time is fake #archived-code-advanced message
to undesrtand it more
got it
well
you should be looking at PlayerLoop then
you can also look at the profiler
you'll see every object in PlayerLoop make an appearance on the main thread in profiler
when you're viewing the timeline
it's just incremented at a fixed rate. As long as the latest one has occurred that you expected before Update happens so you have the right visuals, when it's called doesn't matter.
you will need to use PlayerLoop to do that
or to understand it
good luck out there
in short you will basically never need to touch stopwatch to do this
if you're using stopwatch you're doing something wrong
wut
i'm deleting the message where i said what time.delta time was
yeah
i think that's the takeaway
in all of player loop, there is exactly one place where "stopwatch" is used, and that's if and only if you finished the frame faster than the speed implied by Application.targetFrameRate and vsync
you will look at the profiler and eventually comprehend that stopwatch is not used anywhere in reality
so if you're using it to implement Time.deltaTime, you haven't done it right
for example, if your game renders only 1 frame per second because it's so busy, but your application.targetFrameRate is 60, Time.deltaTime will still be something, but neither 1/60th nor 1.0
Also if you want to live in true hell realise how really hard all this is https://blog.unity.com/technology/fixing-time-deltatime-in-unity-2020-2-for-smoother-gameplay-what-did-it-take
yes, this is why understanding PlayerLoop and looking at the hierarchy in the profiler is essential to comprehending what the purpose of Time.deltaTime is
and what it's actually measuring
wow i didnt know this
this change everything
alright hahahahaha
you don't know what it's measuring is the problem
it's estimating how long until you will render
so that by the end of Update and the start of OnBeforeRender, the right amount of movement has occured
yea
yea thanks for help
Thanks 🙂 I'm having a look
How does Dependency Inversion Principle not violate SRP? We will also have to take over responsibility of satisfying abstraction... Also using DIP implies having circular references between assemblies
There isn't a short answer. Why do you think it violates SRP? And circular references suggests you have things tightly coupled still, which is exactly what you're trying to avoid with DI
A breakdown of the update loop and how deltaTime is calculated
yea vertx linked that
I saw an example with a class which parsed some logs in various formats to the needed one and pushed it to a database. As example of DIP there was created an interface with the method of parsing which further would be implemented by different log classes
Here I see how log classes also contain responsibility of providing parsing implementation and also depend on the interface supposedly located in the same assembly as the class which will call parse method on logs
that suggests the interface is probably in the wrong assembly
or that this should not have been split into multiple assemblies
Man I don't know... I'm only trying to learn it so I don't know what's wrong what's not here. But I see that log scripts would not only have their basic responsibility but also responsibility of implementing parse interface and that there's going to be some reference mess. Please tell me where I am wrong if I am
don't think of SRP as things the implementation does, but of domains that it touches. Does it make sense for a script that parses a log to implement a parsing interface? Sure, no SRP violation. But if it does anything with a database, now you have a problem. So you extract the database portion into its own bit, hide the parser behind an interface so database doesn't have a hard dependency on it, and database now has a dependency on an interface. Which is not its problem, satisfying that is up to the caller. And so these dependencies all get pushed upwards until you encounter a composition root
Actually, it's the other bit a feel bad about. The one where class which is simply supposed to represent an unprocessed unparsed log file and yet it is forced to implement a parsing interface and that leads to having 2 responsibilities (more than 1 which violates SRP). (I've already pointed at it twice and haven't got an answer, am I not asking correctly or not understanding the answer????)
Maybe I misunderstood you originally. Yes that is a SRP violation. Why does the class that does parsing know anything about a file at all? If you iterate it out:
ThingWhichParsesAndIsAlsoAFile
ThingWhichParsesFiles -> File
Then you can see ThingWhichParsesFiles still knows way too many details. Hide it in an interface:
ThingWhichParsesFiles -> IFile
Then you can wonder, wait what other thing could file be? And hopefully leads to to realize that there's a code smell still, ThingWhichParsesFiles doesn't really care about where the data comes from:
ThingWhichParsesStreams -> IDataStream
now IDataStream can be a file, or a chunk of memory, or a database. ThingWhichParses streams parses data from some source. Everything is nice and neat
-> means dependency btw, in case its unclear
I agree with you but still I was asking not about the parser class but about LogFile class which, as I said, is simply supposed to represent an unprocessed unparsed log file and yet it is forced to implement a parsing interface and that leads to having 2 responsibilities (more than 1 which violates SRP)...
why is it forced to implement a parsing interface? If it's an unprocessed, unparsed log file, it is data and doesn't have behavior
Right
split it into LogFileParser and LogFile to start with. It sounds like ThingWhichParsesAndIsAlsoAFile, and if your question is why didn't they do that, it's because where to draw the lines can be subjective. My experience with DI/Solid/IoC in Unity is: don't. This makes more sense for enterprise-type applications that need unit testing and will be supported for years
So should it be like that? Maybe even without the abstract class? Please tell me how you would modify it to comply SOLID and why
do your two concrete parsers share enough implementation details to have a common base class like that?
Not necessarily
If there are more types of log files then most probably there won't be a single parameter shared among them
So most probably abstract class is useless
I'd delete it then, and the parsers can implement the interface directly
Sure, anything else?
depends on how crazy you want to go with SOLID. Technically speaking, both of your log files can be hidden behind an interface like I mentioned before. Right now you have a hard dependency for both of your parsers
In my opinion the data stored in any class can be either given or taken so it's respectively either adding responsibility over providing data (which violates SRP) or making a hard dependency. Is it not so?
you think a file providing data violates SRP? Why? That's right in file's domain, no?
Just because storing data and providing data are 2 different things so 2 separated responsibilities, no?
Don't think of it in terms of what it does. Think in terms of what domains it works with. A file interacts directly with the disk, so saving and loading data from disk can be things it can do without causing an issue. But if it has to format the data too, now it's interacting with the disk AND providing a view on that data. So the question is, are those two responsibilities closely related enough that they make sense to be in the same class, or should that logic be extracted out?
can you give 1-2 more examples?
examples of what exactly? I'm not sure how to answer. Maybe it's easier to think of different people in control of different parts of your program. The accountant decides how the calculations are done, gfx designers decide how the ui looks, etc. Then when you look at a class, you decide which person should control it. If it's more than one, you have a SRP violation
I've got completely confused with that people example.
I was asking for examples of kits of entities/classes, domains they interact with and the things the entities/classes can therefore do
I guess I'll try to read Clean Code instead of wandering the web and asking here
I always liked "The Practice of Programming" myself
game code is always pretty dirty
line of business and backend engineers get hung up on organizational practices. that stuff, like dependency injection, is negative ROI for most video games
one reason is the best game innovation is done by 1 person
if you architect your game to be worked on by 10 people it has already failed
you don't have a $400m budget like Riot does to clone games. there, Big Code makes sense
one of my favorite interns got the job because he wrote a funny joke in a comment
that said, 10 years later and he's still a garbage engineer. does that matter for things being made in Unity? no
logging in games is low ROI
just topic from an article
anyway you're at level 2 of the expanding brain meme of game engineering
as you gain levels you'll see what @long ivy said to you:
My experience with DI/Solid/IoC in Unity is: don't."
i advocate to learn unirx & unitask. at higher levels you learn the coding superpowers are about expressiveness, performance and how few bugs you create
well I think at my level I should mostly stick to these non-unity practices and only then advance to unity-specific ones
How can I read data outputted from a blend tree? Like, the position of various bones, and stuff, from an animator component, instead of applying to a skinned mesh.
Ok, how do I debug something like this? ><
My terrain-blend-edge detection algorithm seems to invert on the X axis. Or it's the data that fed into it, because the algorithm does not do anything like that...🤔
I have no idea what I'm looking at
Not sure if this the place to post this but..
Been looking around and could not find much info on this, maybe you guys can help. I am attempting to make a very simple card builder in Unity. I want to be able to take some png's from a file and essentially layer them on top of an image or something and then put them together and export it out to a normal PNG making a card. Something like this http://www.hearthcards.net/. This is used to make hearthstone cards with set png's.
Is there a way to make something like this in unity, and allow for the exporting of a PNG card file?
Here you can make custom Hearthstone cards.
I know this is a website, but is something like this possible in Unity?
Here you can make custom Hearthstone cards.
The plane is a a procedurally generated "2d terrain" blending between different textures based on a heightmap. And the white lines are just debug gizmos to test the "edge detection" algorithm, that's supposed to get areas where there's a transition between 2 terrain types.
But yeah, I didn't really expect anyone to react, so I didn't provide much info, hahah...
Figured that out if anybody cares. Since I define terrain data at virtual vertices, not "tiles"(a quad of 4 vertices), when using the "terrain resolution"(basically tiles count per axis), I was actually offsetting the position on the X axis each iteration(row), so it looked like it was inverted. But it was actually skewed. Sampling the points at the correct indices y * (res+1) + x instead of y * res + x, I got the correct result.
Now it looks more like an avocado
Most definitely, yes
like any gamengines out there, there are learning curves in Unity as well..
Most users hated it when they're told learn the c# language 1st, but that's the truth whether you like it or not. There's some shortcuts, like buying a premade templates on Assets store, but trust me, to get your dream game come true, you'll still need to learn c# especially in Unity
It really depends on what you want to do, if you want to become a programmer then learning C# separately is the best way, you can still learn C# and Unity at the same time however you should be aware that it'll teach you bad practices and it'll take significant effort to unlearn those.
If you just want to create a game and don't care that it is hacked together, feel free to do whatever you want in whatever order
All those folks learned c# via Unity got some serious inheritance problems 🧐
This so cool dude
If you think that's cool, how about this? 😄
There are still a lot of edge cases where it does not look great😮💨
What do you think of "Interfaces should be adjectives. Abstract classes should be nouns." If I have to create an abstraction of a file for example, I'll ask myself if it is a behavior or a thing ? Then, I'll either create a File abstract class or a IParsable interface, what's your take ?
I’m curious about the abstract vs interface thing too. Actually ngl i thought interfaces were more closer to Actions/Events but thats prolly me
I’ve never had any uses for interfaces except for IDamageable lol
not really
That’s the only way to make them somewhat not a PITA in unity
tho since c# 8 interfaces can do body implementation as well, but still
interfaces (in unity) only make sense if your project is built in a way that you do not rely on builtin editor features much, for the system that uses the interfaces. Basically making interfaces work for you (in regards to improving maintainability) is to use a lot of custom inspectors
Actually this makes sense
A car and a box are not related at all, but both can be damaged
Yea as you can see i can only use damageable as an example lol
Adjective = Interfaces describes an attribute that a thing has independent of what it is derived from… it’s exactly what you described
not using abstract makes it impossible to reference your shared base type in the editor
testing is not a good enough reason to avoid them in most cases
Seems to me like a bunch of boilerplate just to make tests work
but if you do that to do some sort of composition/aspect oriented programming I’d agree that’s a good thing
Fair enough
Suppose you work in long term projects mostly?
ic
I think testing (TDD) is only a financially sound decision if the project runs longer than 3 man(person)-months
Can appreciate that sentiment 🙂
it’s nice to have tests, not so nice to write and maintain them
Depends a lot on the test strategy. Writing tests during prototyping is useless, and it’s hard to go into slow-mode dev with tests after that, especially if there is no discipline about rewriting everything if a spec changes
Does anyone know of any good machine learning modeling software?
Try making an Interact system (just a simple ray from the cam that detect something) and you’ll see how useful “IInteractable” can be
I'm trying to set up several markov equations in software format. I'm just trying to find the best way of doing this.
What does that have to do with democratization? Afaik TDD was hyped a decade ago, got popular as a buzzword but reality showed that it’s only a sound investment if it fits the product’s lifecycle
There are a lot of strategies you can take towards testing
Dogmatic TDD for everything is just foolish
Also you can do a lot in the actual code to test and communicate assumptions/contracts
It’s always a good idea to have them, but you need to judge their value against their cost. Only if you do that does it become an argument. In theory they are always good.
therefore in longer projects their value increases
in short projects you start with double or triple the cost over manual testing, assertions and a few simple integration tests
But testing games is inherently hard, no tooling can ever fix that
Unity does the opposite of making it easier though
Different methodologies can. If you keep your monobehaviours humble and your logic in plain, SOLID classes, testing is very easy
it might take years for it to become ROI positive. even for a game that becomes a hit and earns a team
you can use UGUI. it is, essentially, Photoshop Lite
what is your objective? creating educational materials about big picture programming using Unity as a hook?
Not at all, I was just curious to hear folks opinion on this, thanks to those who responded btw
if i called a method from inside a task will the method also be run through that task
Does anyone know how the map generation works in Vampire Survivors?
i'm trying to create a similar thing
I tried making a tilemap that has 4 empty objects inside of it (in each corner of the tilemap), calculating the distance between the player and each of these objects and then generating tilemaps in different locations, e.g. above the current tilemap, to the right of the current tilemap and in the top-right of the current tilemap
but firstly, it generates duplicate tilemaps, and second (though, I think this may solve the first problem), I dont know what to do after I place the tilemaps in the correct position. What do I do with the old tilemap?
yes, but a task is not a thread
if the method does a bunch of work in C# code that is like, a big for loop, and thus it takes a long time to complete - as opposed to waiting for a web request or waiting to write a file or some kind of IO/specially handled thing - the thread running the task will be blocked. if the task is being run by the main thread, the main thread will be blocked
If you only talk about unit tests then yes. But those are not as effective for testing most games as they are for testing web services
Ah yeh i forgot about IInteractable
Even IPickupable is also good
Anything that uses CompareTag can replaced with an interface
Okay thank you. It is just for big loops and such
hey there! this is the first time i'm working with Pooling, and i'm struggling to replicate a certain behavior
essentially, instead of Instantiating bullet holes and then destroying them after X seconds, i want them to never disappear
but after reaching a certain amount of total bullet holes in the pool, the oldest bullet hole is recycled instead of a new one being Instantiated
all Pooling tutorials i have found only use the first behavior (so destroying them after X amount of time) so i don't really see the point
is it big loops accessing and modifying things that are in your scene?
you can resize the pool
set the lifetime to Mathf.PositiveInfinity
and resize the pool
the way compare tag is used, you don't even need an interface. you can do
if (other.GetComponent<ComponentOnlyOtherHas>() != null) { ... }
which is to say, components already are traits, in the way that interfaces are traits
and people like to reinvent components
yes but ive figured that out
I meant more like if many objects share the same sort of method but different functionality, e.g with IPickuable. Instead of checking if you picked up a Medkit or a Speedboost and then getting their respective script, you can just check if the object you collided with has an IPickuable interface in it and call some sort of a Pickup() method
Same for IDamageable. Instead of checking if it hit a player or a crate or something, just check for the identifier and call its method
That’s my initial thought atleast. Basically if you got many different objects that does similar things, it’d be better to just use one identifier instead of comparing many tags
Is it possible to use the animator for my own ends I guess I’m trying to ask?
you can create a component called CanBePickedUp
and attach it to medkit and speedboost prefabs
You can use a UnityEvent onPickedUp and wire it up to your Heals component or your AddsSpeed component's respective methods when you build the prefab
Wait why would you do that when you can just use IPickupable interface ? I don't see any benefits
edge cases
(¬‿¬)
i am trying to illustrate how components are already interfaces in that they are each representative of composable behaviors
this way you could make .eg. a single Heals component and add it to an item, an area of the map with a trigger, a monster, etc.
the prefab component model is pretty much purpose built for creating platformer levels and monsters
This is just a wrong understanding of what interfaces are for IMO
Or maybe the context in which they are useful for a game
Ah, alright yeah, there is always a thousand ways to achieve any goals
^^
Ok but then you need an CanBePickedUp component on every single object of a different unrelated type that can be interacted with in that fashion
It's just bloat for no reason
every single object that can be picked up will need a component that implements that, eventually, yes.
it's unavoidable
you will have to put the code somewhere
an example of where interfaces are just no nonsense imo: I have a bunch of different object types driven by completely different physics code. Players, pickups, projectiles, props... they all need to be pushable, but they all have different unrelated methods of calculating forces/collisions
So just make a IPushable interface
i offer that since there are many things that can be picked up that aren't items in platformers
Yea
for example, quests, corpses, etc.
it really depends on what kind of game you're making
There's just less stuff to track with the interface
the reason unity has the component model is because it's sort of what flash had
they didn't htink about this
You implement the GetsPushed() function in your component directly, don't have to play with references
but flash had it because shockwave had it, and shockwave has it because for designers it helps them be creative
by composing their little pieces that the engineers made
For getting a reference to the interface I have a reference table
You just do collider.GetPushable() and it's done.
so in terms of making a good game... ia dvocate for making lots of little components, because the psychic experience of clicking aroudnt he inspector and searching by text for things you want to put together helps you create innovative new monters, items, etc in your platformer
this should help illuminate how you have spent more code in a more arcane/obscure way to achieve the same goals
It's < 20 lines
and i've had this conversation with people before here - yes,l you always need to write code to achieve things
it's unavoidable
people have long arguments about where to put taht code
and i bet you your 20 lines look really arcane and obscure
With the component approach you still have to implement each case individually in the component that drives the behaviour
In fact you may as well use an interface for that part!
Atp it’s pretty much prefrence on how you do it 💀
indeed.
you have to write code to achieve things
if( collider == null ) return null;
return m_References.GetOrCreateValue(collider).thing;
}
public static void SetThing( this Collider collider, MorosThing thing ) {
if( collider == null ) return;
if( thing == null ) {
MorosReferences r;
if( m_References.TryGetValue( collider, out r ) ) {
r.thing = null;
if( r.IsEmpty() )
m_References.Remove( collider );
}
} else m_References.GetOrCreateValue(collider).thing = thing;
}```
really is the simplest thing in the universe
Plus if you're looking at this from a team perspective, the "designers" don't need to know about any of this
The work in your case happens in a different area
in the least obscure area, in 1 line
you still need a line for SetThing()
you still need to be aware of these
GetThing and SetThing
you haven't strictly reduced the burden of what components and interfaces are
You have to maintain references between the components and the IsPushable component, then you need to implement all the behaviour for the individual objects in IsPushable component. It has to know of all the object types in your project and find/maintain references to them
it is a matter of opinion if you've increased the burden (intellectual or otherwise)
in my opinion you have
yep, that is true
The behaviour for the pushing should be the responsability of the underlying object, not the compatibility layer : S
you have to do that
you have to do that no matter what
no matter how you do things
somewhere, you will have to write code
If I write a new object type and someone else does as well I have a merge conflict with IsPushable component now.
that makes the special behavior of something being pushed
If you use an interface, its implemented in the underlying component. No merge conflict, no problems.
that's true, sometimes in programming there is a merge conflict
i don't think having an IsPushable component is a good idea
i don't think checking the types of things is either
Maximize merge conflict, minimize productivity B-)
i wouldn't implement it the way you did
anyway
i guess my point is that you are welcome to use interfaces to recreate the unity component system
they really are duals of one another
anything you can do in one, you can do in the other, and vice versa
that's like, how they are conceived, at a theoretic level
that's all i'm trying to illuminate
FindObjectsOfType is your "reference table"
if you look carefully you will see these things are duals
That's true
it's okay
but that's not the part that's better. The improvement is that you minimize the points where the code is touching. The behaviour is implemented in different classes, and in the class where it's most relevant and where all the information is available
Having the Pushable component have custom logic to handle every object type in your game is gonna turn into spaghet the more people are working on it and the more object types you have
If you don't use this method and instead you have it refer to a virtual function called on the destination object then it's basically identical to an interface with the added downside of forcing inheritance
You're handwaving this away like "so what merge conflicts, shit happens" xD. It's silly
People who don't understand your custom system are inclined to ignore it and implement their own way/workaround, maybe they are just unaware how it really works and next to the 100 important things they need to know to get stuff done, it might just get used in the wrong way or you spend a lot of time explaining the why and how to them
My custom system is irrelevant to the use of interfaces
It is just one example of an implementation of it.
I was trying to provide a concrete case
the more basic and commonplace the patterns in a project are the more likely it is that people in the team will use them correctly
Add a Pushable component, the pushable component looks for a component on the object and casts it to an interface
There you go, now you're using the Unity component system and you have all the advantages of abstracting the behaviour out.
The reference table thing has nothing to do with my point, that's just how I did it because it results in less spaghetti in my particular case
I'd do that when there is an apparent need to abstract behaviour, not before though
so with all things, engineer more when there is an apparent need to do it, but don't start with XML
But on a big project where there are lots of ways to interact with stuff (IDamageable, IPushable, IPickupable, IUseable...) it's obviously extremely useful
maybe, but i think such projects don't really exist in the sense where your game-dev code team is so large that they need interfaces to manage their work across teams and time
i'd say interfaces would be more suitable to abstracting larger modules than "IDamageable"
I don't want to have to stop working on my crate pushing code to resolve a merge conflict because someone just added a beach ball and it responds to pushing with different physics code, and now I (or we both) have to edit the player physics code to have different pushing behaviour.
This will manifest with literally two people
this sounds more like an architectural problem
you don't solve architecture problems with language constructs
nothing is more damning to interfaces than interfaces implemented by exactly 1 class
even ICinemachineCamera is implemented only 3 times
and once you see how, it'll be clear that it is a convenience
and that's a very complex and low-bug unity library
tbh, i tend to create interfaces all the time, only for them to be eventually replaced by that singular implementation
yeah and i wish more people would just
do the things that help them think
as opposed to worrying about like, what happens when 10 people start working on this codebase, which never happens
How would you start?
also another reason i advocate for unirx & unitask so much - it frees your mind for how to think
and why i think people advocate for seemingly low ROI things, like learning haskell - it's about helping you think
yes, 100%
critically, it is impossible to procastinate using UniRx. what are you going to do... make more triggers? cygames guy has made them all
however... making glorious type hierarchies... very easy to procrastinate doing that
tradeoffs to everything
there is a "glorious type hierarchy phase" to a programmers maturing as a developer 😄
Why not?
there's no such thing as a test called void IsFun()
Yes, that’s the part I use it for the most often, I also use it for “IKillable”
you are only partly correct, there is a test
bool isFun() { }
but it is rarely implemented
I'm trying to keep my script on gameobjects with a list of all my scriptableobjects that are in my project. That's easy to get but I need some way to update it as a scriptableobject is created. OnValidate works mostly...it doesn't trigger when one is created. Is there a way that when one is created to update my scripts with the new scriptableobject? This is in Editortime not Runtime.
Are you listing scriptableobjects for use in like an item selection or something?
...except when they're implemented in a different assembly.
Nah. A tagging system where the SO are "tags". I just need to know when they are made and whatnot so I can update my custom inspector
Hmm. I'll look into that.
On the scriptableobject at least, it's called when it's created
...but I do often write to do comments \\TODO: make this fun
might need to change the type name to UnfinishedTechDemo instead of Game
then it would basically be my implementation as well
IEnumerator DatabaseDownload()
{
WWW www = new WWW(webURL + publicCode + "/pipe/0/10"); //Gets top 10
yield return www;
if (string.IsNullOrEmpty(www.error))
{
OrganizeInfo(www.text);
myDisplay.SetScoresToMenu(scoreList);
}
else print("Error uploading" + www.error);
}```
guys, my WWW have that green underline, so i put [system.Obsolete] and that green underline is gone so now there's no issue. But i have to ask, it is ok right? because the tutorials didnt ask me to put system.obsolete.
You are obviously following an old tutorial WWW has been replaced with WebRequest
Hello, I want to make a render texture in runtime (runs once per scene) with the exact pixel size of a rawimage that draws it to the UI, but I cant find anything about about getting the screen resolution of the rawimage.
(dotted line is flow of control and the red one is dependency pointer)
I can't understand... the book (clear architecture) says that the source code dependency between MLl and the interface I points in the opposite direction compared to the flow of control but they (arrows) are not opposite, are they?
The green one is moving down the tree, the red one is moving up?
It's definitely not the same direction
But they do not look opposite to me either
The book is not saying that they are opposite, it's saying they point in opposite directions
One is pointing up the tree, the other is pointing down the tree
Would you like to separate runtime data from logic?
For example, in strategy games, there are runtime data like population, resources, etc. They are updated at runtime while playing. A class which contains just data and another class to manipulate runtime data.
Also what do you prefer to name them?
RuntimeResourceData/ResourceDynamics and ResourceManagement (logic) for example?
OOP is all about containing the data and logic within an object, so no, I wouldn't wanna do that.
I'm sure there are some data-driven principles out there that disagree, but I don't agree with that approach for general use.
sounds the same to me fairly
Supposedly, an arrow would be a line pointing from some point A to some point B. The opposite of that would be B -> A. The direction is merely a part of what makes an arrow an arrow 🤷
doesn't make sense for me eitherway
Heya! I'm trying to create animation clips based on some imported json, I can create rotation and position curves just fine however when I try the scale curves (docs says they should work) they don't show up in my clips. ```cs
if (script.positions) {
var pos = item.localPosition;
var x_curve = AnimationCurve.Linear(0, pos.x, 1, pos.x);
var y_curve = AnimationCurve.Linear(0, pos.y, 1, pos.y);
var z_curve = AnimationCurve.Linear(0, pos.z, 1, pos.z);
clip.SetCurve(path, typeof(Transform), "localPosition.x", x_curve);
clip.SetCurve(path, typeof(Transform), "localPosition.y", y_curve);
clip.SetCurve(path, typeof(Transform), "localPosition.z", z_curve);
children[i].position = resets_position[i];
}
if (script.scales) {
var scl = item.localScale;
Debug.Log(scl);
var x_curve = AnimationCurve.Linear(0, scl.x, 1, scl.x);
var y_curve = AnimationCurve.Linear(0, scl.y, 1, scl.y);
var z_curve = AnimationCurve.Linear(0, scl.z, 1, scl.z);
clip.SetCurve(path, typeof(Transform), "localScale.x", x_curve);
clip.SetCurve(path, typeof(Transform), "localScale.y", y_curve);
clip.SetCurve(path, typeof(Transform), "localScale.z", z_curve);
children[i].localScale = resets_scale[i];
}
}```
Hello, i made this player controller script https://pastebin.com/LZ139Mps. When I move my mouse it seems to be working properly, but when I put my mouse to a specific spot on my desk, and look at a specific object in the game, then move my mouse around really fast and return it to the original spot, the player doesnt look at the object anymore, although I returned the mouse to the exact same spot it was in before. So it seems that the game isnt picking up the exact mouse movements. Is there any way to fix this issue?
I would probably multiply not only with mouse sensitivity, but with Time.DeltaTime as well. Otherwise your code will give different results based on framerate, which might be the cause of your error.
The mouse input is already a delta
Many people get that wrong
don't multiply mouse input by delta time, it is already frame rate independent
Doesnt help that they do it in the documentation examples. 😮
By the way, I tested other games and they all have the same problem. Not as noticable as in my game though
they don't though. they show multiplying the Vertical and Horizontal axis by deltaTime, but do not do that for the Mouse X and Mouse Y axis
likely a DPI/hardware issue. not really a whole lot that can be done except by maybe adjusting the sensitivity 🤷♂️
Okay nothing to do with this problem but i changed GetAxis("Mouse X") to GetAxisRaw. Now its completely weird mouse movement. Why? I thought GetAxis just applies some kind of smoothing?
I have a question as well: How would you convert data so it can be shared between different clients? If the game features a level editor/creator that exports all data to JSON, what is the next step so I can send that data to my friend so he can play my level? What is the keyword I should google? I guess you could upload it to your server and create a url, but are there other options available?
mouse input doesn't have smoothing applied. GetAxisRaw only returns -1, 0, or 1 which of course wouldn't make it be a proper delta (at least that's my understanding of what is happening)
Oh okay I see
this would probably depend on how you intend to handle networking in the first place. like are these levels that are stored locally on the player's machine and only shared when in a multiplayer lobby or whatever? if so, just send the json data from the host (or client that owns the data) to the other player(s) over the network and store it locally on their machine. or your idea could work where it is sent to some server and downloaded via a GET request. probably better off asking in #archived-networking though
hey guys
how do I correctly dispose of persistent NativeArrays that supposed to live until a scene change or application exit ?
when I dispose them in OnDestroy / OnApplicationQuit of the behavior that holds the reference it says that arrays are already disposed
if I don't, it says that arrays were not disposed
you could just check if they have been disposed already in OnDestroy:
if(nativeArray.IsCreated)
{
nativeArray.Dispose();
}
I'll give it a try, thanks 👍
Implement the IDisposable interface in your class
it worked, thanks again ♥️
curious why though, looks like something can dispose those before the owner's Dispose method could. But it's not consistent and doesn't dispose some of the arrays in some scenarios. Or something like that
Does anyone has code/worked on attraction-repulsion model that can share with me?
I have a pretty hard coding problem, please check it out: https://stackoverflow.com/questions/73099351/how-to-fix-this-glitch-where-the-player-snaps-right-back-to-the-previous-positio
I'm currently making a multi-player game where I use a singleton for the game manager to access an array that every player will be reading and writing to, which is ok.
However, I need a way for the bombs every player drops to access the stats of the player so they can act accordingly (power, and maxammo count, and probably others in the future). I realize that using a singleton to access something like player stats would be potentially problematic down the line. Do you have advice as to how to structure this in a way that is multi-player proof?
Sorry, I'm a bit new, and I haven't looked too much into how the implementation of multi-player would go, I just have a feeling that using a singleton for something like this potentially a bad idea. Thanks.
you cannot teleport an active CharacterController. If you want it to teleport, you have to disable the CC component just before the move then reenable it right after the move. Alternatively, you can call Physics.SyncTransforms() just after moving the object and the CC will not snap back to its previous position.
Give the bombs a reference to the player that owns them
You could also use a Dictionary to map bombs to the player that owns them
Are you aware of this talk? I would use a ScriptableObject for your problem. You store each players values in its own ScriptableObject that is referenced by the bombs.
https://youtu.be/raQ3iHhE_Kk
Scriptable Objects are an immensely powerful yet often underutilized feature of Unity. Learn how to get the most out of this versatile data structure and build more extensible systems and data patterns. In this talk, Schell Games shares specific examples of how they have used the Scriptable Object for everything from a hierarchical state machine...
documentation says it's not a good idea to access static data from jobs, does it mean literally anything that uses the static keyword ? even things like a read only dictionary in a static class ?
I'm using one instead of a long switch expression, wonder if it's ok or maybe it will cause some hard to track stability issues in the future
You definitely don't want to be accessing managed data from a job at all
Native collections only typically
yeah, makes sense, everything else is inside nativearrays, I should definitely just rewrite that small section, thanks 👍
Not a code issue, much less an advanced code issue
but put the project somewhere else other than the desktop
and not spaces in the project path
thanks so much it worked
i wouldn't stress about it. do whatever winds up working.
the simplest thing is to always access things like stats via an argument that signifies which player is being accessed (e.g. "player index 0")
it's better to use input system where this is all less ambiguous
I am getting this error: There is no argument given that corresponds to the required formal parameter 'checkPlayer' of 'Combat.RpcOnReceivedDamaged(int, DamageType, bool)' trying to call this command victimCombat.RpcOnReceivedDamaged(damageDealt, damageType);
[ClientRpc]
public void RpcOnReceivedDamaged(int amount, DamageType damageType, bool checkPlayer)
how do I add checkPlayer? I tried Player, player, checkPlayer. nothing worked
not an advanced issue. and that error message means you didn't supply all of the arguments the method was expecting. you need the last argument which is a bool in your method call
Its advanced for me :( how do I supply that argument?
I tried player, checkplayer, and Player
go back to #💻┃code-beginner and check the pins. there are beginner courses in there, those courses will teach you how to include arguments when you call a method
Ok tyvm
This is wrong
I tested it just to be sure
Left hand is GetAxis, right hand is GetAxisRaw
well then i have no fucking clue why GetAxisRaw gave different results than GetAxis 🤷♂️
I thought that GetAxis applied smoothing, but right now it seems to do nothing different
But definitely GetAxisRaw does not lock the mouse input to -1/0/1
GetAxis does not apply smoothing to mouse input
Yea
Seems to be exactly the same
Definitely though GetAxisRaw does not clamp input to -1/0/1
That's the one that I use in my actual FPS game and I'm pretty sure you would be able to tell if it did!
I haven't personally noticed any mouse accel in Unity
Do you have enhance pointer precision on? And sensitivity in windows settings set to 6th notch @glad scroll
seems that way yes
I'm not sure how you might want to answer this question if you're not sure yet how your multiplayer implementation will work. You're basically asking if a design pattern of which you haven't yet explored the consequences will work with another unknown design pattern you haven't decided on. Use what makes you comfortable. I can't think of any general reasons why a singleton would somehow prevent you from having multiple players, local or in networking. If you don't intend to be running more than one game at a time then having the game manager be a singleton sounds reasonable, no?
Just use what makes you comfortable for now. When you have more information about what you want to do you'll be able to make more informed decisions
With occlusion culling, is it possible to tell Unity to sample from another point besides the camera transform?
I'm working on a game where the player can shrink, and occlusion culling culls stuff it's not supposed to if you're too close to the ground on sloped surfaces. I've tried adjusting the size of the volumes, but that leads to the occlusion culling then not culling things it should, and the computation time and data size balloons.
I can't simply scale my world up, as that creates way too many issues with things like reflection probe volumes and other stuff not scaling with it.
So what I'd like to do is tell the occlusion culling to sample from a certain distance above the player when they are small, because down to around 10cm tall it works fine, but I'm trying to get down to 1.5cm.
This doesn't seem like the right channel for an Occlusion Culling question...
What channel do you think would be right for it? I couldn't find one where it seemed appropriate. It's not shaders, vfx/particles, post-processing, urp/hdrp, or lighting.
#💻┃unity-talk is where things go that fit nowhere else
That seems like a channel where advanced questions go to die. "Non-programming questions and stuff that doesn't fit elsewhere"?
with scale that extreme, wont you also encounter problem with physics?
I don't seem to be encountering any issues with physics. That's an issue I would have to tackle if I encounter it I suppose. Increasing the number of computations might help with that?
I did just find this blog post which contains a couple potential solutions: https://blog.unity.com/technology/occlusion-culling-in-unity-4-3-troubleshooting
Generally, when the backface test is enabled (i.e. when backface threshold is something smaller than 100), Umbra will do a better job near occluders, because it is able to detect the insides of occluders, and correspondingly dilate all valid locations slightly towards them, so that you’ll get correct results even if you go arbitrarily close to an occluder. So if you cannot prevent your camera from going very close (or even slightly inside) an occluder, the first thing you may wish to try is to set backface threshold to something smaller than 100. This will help with dilation and may fix the issue.
If tweaking backface threshold does not help, or if your camera goes very deep inside an occluder, the only thing left to do is to simply remove the occluder flag from the object.
I wouldn't have even thought to try lowering backface test. That seems like it could only make the problem worse. Of course, lowering smallest hole also seems like it should not have fixed the issue with my culling since my problem was not enough objects were being culled, but when I found this blog and learned the system works on voxels I realized that it was probably discarding my interior walls as occluders.
And setting my ramp to not occlude also seems like a viable solution if that doesn't work.
Though I have so many sloped surfaces maybe that isn't viable.
this seems like a hack, but how about when you are small, disable occlusion culling and reduce visibility range (if needed, just incase frame rate drop)?
I don't even know if disabling occlusion culling is possible. Well, not without traversing every object in the scene and turning it off. But even if it is, the framerate drop would be too great. And reducing the visibility distance would probably not work well. My sky for example is not a standard skybox because the mirror system I'm using it requires it to be geometry. So that would end up being culled and I'm not sure how I'd stop that. But also I would have to reduce the distance so much it would cull very visible large distant objects. It would just be so easy to fix this if I could just tell the occlusion culling system to sample from a different point 0.1 meter above the player when small, it would work without issue 99.9% of the time.
Well it is possible to disable it per camera, so that's easy enough but still, massive fps drops if I do that, so not a good solution.
I wonder if it would be possible to move the camera before the culling phase, then move it back in the render phase. But I don't know how well that would play with VR. I had an issue with a menu camera updating choppy when I tried to make it follow my main camera with a constraint.
You can try using a smaller voxel size for your occlusion. As in, a voxel size that would make sense at the minimum scale of the player
The builtin occlusion culling system is mostly blackboxed though. There's no way to really hack into it that I know of and I've looked into it a few times. This sounds like a case where you should be building your own system
Reducing the voxel size to that scale is probably a terrible idea btw, it's going to make your pvs data hueg. But it might work, no idea what impact that's going to have on the CPU afterwards though. You can maybe check if it is indeed the static component of the occlusion system that's causing objects to disappear or if it's dynamic occlusion. Those two systems are seperate and I don't really know how dynamic occlusion is handled but I've had some problems before where dynamic occlusion was causing objects that should have clearly been in view to disappear when inside very tight spaces, like a vent or something
I'm currently using a smallest occluder of 1 and a smallest hole of 0.05. I've found that reducing either of these leads to very long bake times, and large data sizes, but those I could live with. The real problem is that those seem to be the only settings that actually work well. I have a house with relatively thin walls, like most houses have. And for the longest time I could not figure out why nothing was being occluded inside the house. It wasn't until I found those blog posts from 2013 explaining that the culling system voxelizes everything rather than using polygons to determine visibility, that I realized what was happening was likely that voxels overlapping those walls were partially inside the rooms of the house, and so they were discarded as occluders. I then tried smaller values for smallest hole, which I had previously assumed could only cause MORE objects to be hidden if it was too large, and lo and behold it started working as expected.
But here's the thing... I found the sweet spot was 0.05 for the smallest occluder, and that for some reason, if I went smaller than that, even though there's clearly walls blocking the player's view from outside and there's no gaps in the structure, certainly none which are larger than a millimeter, I started seeing objects inside the house that should not be visible showing up. So if I were to go lower, while it might stop parts of the house from disappearing it would also negate the point of occlusion culling because it wouldn't occlude half the stuff.
I mean
So the way it works is it reduces the world into a bunch of bounding volumes and pre-calculates which objects are visible from which volumes, right
The voxel approach is kind of obvious for that
It's not the best system ever and it's definitely not fool proof, if you need more accurate occlusion you really have to use some kind of custom system. There's someone out there that wrote a Unreal style GPU occlusion culling system, I think it's on the asset store. If you have no interest in figuring out how it works on a technical level I'd say just try that one. It probably won't have the same problems as the Unity one.
Yeah, and that may be the route I take, since it seems like there is no way to offset the location from which its sampling that would have been the simplest solution.
But it annoys me that the docs were so unclear about the voxel thing. "smallest hole you can see through" does not inform you the world is being voxelized and they say nothing about thin walls being missed if that value isn't small enough. I'd never have thought they were converting stuff to voxels to determine visibility and every time I've asked about why the system wasn't working nobody seemed to have any ideas. Hell, the devs of Budget Cuts even commented on having to delay the game to roll their own culling system because the Unity system did not work well enough. Makes me wonder if they just had the same problem I did not understanding how the culling data was being built because aside from my issue with it not working well for teeny tiny players, it works pretty darn well, with those specific settings I chose, for interior environments with thin walls.
I'm happy to report that changing the backface threshold seems to have resolved the issue! I do get a few more objects than I expect to be culled not being culled in the house, but it's maybe like 5% more which I can live with. I set the threshold to 50%. I could perhaps set it lower or higher, but I haven't tested those yet. Perhaps a higher value would cull more objects in the house. That would be the opposite of my expectations, but since 100 worked slightly better than 50 is, while simultaneously not working best because it culled more stuff than it should in some cases in spite of that supposing to be the most conservative setting, well... Everything I expect about how this culling system seems to work the opposite, so I guess the only way to be sure is to test.
I dont have enhance pointer precision on and sensitivity in my windows settings is in the middle
hello everyone i have a question, I want to save the player position without updating it. However if I do this in the code below, the startPosition constantly updates because it always the same as the player position. However I want to save the player position once and not update it. I placed this code in a void that gets called when a key is pressed on the keyboard.
public Vector3 startPosition;
...
startPosition = transform.position;
Post full code to #💻┃code-beginner
ok
Here it is #💻┃code-beginner message
@devout hare do u know a solution
so I'm always getting this error now for some reason:
NotSupportedException: The invoked member is not supported in a dynamic module.
{
Type[] types = assembly.GetExportedTypes();
foreach (Type type in types)
{
if (type == typeof(Debug))
{
GetMethods(type, GetIconFromType(type), 2);
}
}
}```
and if I change it to a for loop it works, but then when I reopen the project it gives the same error
and I have to keep going back and forth
The error happens because you are trying to get the location of an in-memory assembly (the ones you have created on the fly) and those assemblies aren't located anywhere.
but I do get the assemblies here:
List<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
if it compiles the scripts, then it works
how can I fix this?
unless the scripts compile first, this returns the error: assembly.GetExportedTypes();
await UniTask.WaitForEndOfFrame();
Texture.ReadPixels(......) ``` shouldn't WaitForEndOfFrame tell unity to readPixels in the drawing frame?
Im getting 'ReadPixels was called from system frame buffer, while not inside drawing frame'
though on editor the 'waitForEndFrame' seems to work, on device it doesnt
ok so I fixed my issue by detecting when the project is first opened, and running this:
UnityEditor.Compilation.CompilationPipeline.RequestScriptCompilation();
You should wait for end of frame instead
oh.. shoot...
you did that already.. then I've no idea
Why not using coroutine? Tasks are always a bit buggy in Unity
I know they're great, but in Unity it's really better to stick with Coroutine for Unity stuff
void StepThroughEnum<T>(ref int indexer) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
indexer++;
string[] names = Enum.GetNames(typeof(T));
T[] enums = (T[])Enum.GetValues(typeof(T));
Debug.Log(enums.Length);
if (indexer >= enums.Length)
{
indexer = 0;
}
int testIndex = 0;
foreach (var name in names)
{
Console.WriteLine("names:" + name);
}
foreach (T item in enums)
{
Console.WriteLine("enum:" + testIndex);
Console.WriteLine(item);
testIndex++;
}
Debug.Log("end enum step");
}```
Does anyone know why this doesnt work?
i get for example "8" as length but the foreach loops both of them just dont log anything
no errors, and the last debug.log also executes..
Here an easier to read code:
void StepThroughEnum<T>() where T : struct, IConvertible{
T[] enums = (T[])Enum.GetValues(typeof(T));
Debug.Log(enums.Length); // for example returned 8
foreach (T item in enums)
{
Console.WriteLine("enum:"); // this doesnt show in the console
Console.WriteLine(item); // neither does this
}
Debug.Log("end enum step"); // This shows up in the console
}```
put a breakpoint and inspect the value of your array
Why are you mixing Debug.Log and Console.WriteLine?
Console.WriteLine doesn't print to the Unity console AFAIK
XD
idk
that was probably the issue anyway 🙄
thx hehe..
Yea it was.... very stupid mistake..
what is the context here?
you can use a custom pass to retrieve the display frame buffer. otherwise you will have to render to texture
look at the timeline view in hierarchy while exploring the output of PlayerLoop.GetCurrentPlayerLoop() in a debugger to fully understand where WaitForEndOfFrame and such occur
is the texture a render texture?
unfortunately WaitForEndOfFrame is waiting until the end of the CPU rendering work in scriptable render pipeline. it does not wait for the GPU work
there are a bajillion ways to get the thing you need. the best is to do Camera.render
hi
thanks for answering
the context is the following... i have a sript that
1.Renders
3.Creates a texture based on the renderTexture assigned to a specific cam
4.Saves the texture in disc
okay
the camera the script captures and renders its a secondary one, not the one the player is seeing
is it essential that the second camera's output be as up to date as possible?
does it matter?
mmm no, i trigger it 1 second or 2 later of a modification being done in that area
its like a satellite view of a city builder
so when player modifies something in area x, i move that cam there, render just a portion... etc etc...
to create a mosaic of 16 textures
that would be the satellite view
1 way of doing it is completely syncronous... i do this is sometimes, when the player 'enters' that view
but in order for this process to take less time
i take portions while theyre playing
so yeah, i dont need to have it fully up to date since player wont see it until he enters that secondary view
I dont know If i answered your question
this is what the script does exactly
1 create rendertexture
2 assign rendertexture to secondary cam
3 enable secondary cam
4 render secondary cam
5 disable secondary cam
6 convert renderTexture to texture (here i use the ReadPixels)
7 Save texture in disc
8 Destroy texture
this is done and the player doesnt even realize that it has happened, just a few ms for each step, but when I call ReadPixels the message ''ReadPixels was called from system frame buffer...' appears. The thing is when i added WaitForEndOFFrame this was fixed for editor, but on device still happens
oh yeah
so
don't get mad, but you know you can reference a render texture in a material right?
that'show your'e supposed to do this
it shouldn't touch the CPU at all
if this is for saving to disk
to make like a preview
use async gpu readback
which i believe will be supported on all your devices
otherwise, use graphics.blit instead of readpixels
yeah but its 16 textures of 1024, then this textures would be all allocated in RAM all the time
what im trying to do is to capture 1/16 of the map and having textures in disc, out of ram, so whenever the user wants to see them, then i load them in a material
and if i do it like this is so the process can be done while the user is playing and doesnt realize, if i do it like you said, takes lot of time capture what we want and show it
plus the usage of the ram
it really depends how out of date it can be
i think reinventing virtual texturing is hard
the best thing to do would be to have a single texture
its 4096x4096... but im giving it a try
you can use jobs to create the images
that is probably the best approach
you would save them as bitmaps onto disk
targa or whatever unity can load on all mobile devices at runtime
i was gonna try the renderTexture approach you mentioned but with 16 porttions and profile memory
i wouldn't do it on the cpu thread
well you can move the camera's view every frame
so across 16 frames image your 16 different tiles
you would still need 16 render textures
also it's possible that pixelRect will let you draw to a psecific portion of the render texture
you sort of want the inverse of pixel rect but that doesn't exist
you can't specify 16 render textures for 1 camera in unity
but this time i would do it syncronously because i would do it during the trransition of one mode to the other (theres a fading effect)
it's going to be really slow
i mean
i don't really know
i guess you'll find out
the reason it's slow is because it touches the cpu
and modern graphics are pipelined
you never want a dependency in the main thread on something that comes out of the end of the "gfx" thread (meaning the gpu)
that's what async gpu readback is for
to let you keep pipelining
let me get a hold of this...
right now this is heavy because im relying on CPU
is it correct?
it's heavy because you are waiting on graphics
you are doing no work
you'll see it in the profiler
it's also what that error message is really trying to say
it's trying to say "you are interacting with the modern graphics pipeline incorrectly"
once you look at your profiler in timeline view
and look at the main thread, the render thread and the gpu rows
you'll realize how this works
async gpu readback , you mentioned this would help me
because it is a way to express to unity that "the next frame does not depend on the work i am doing right now"
unity doesn't know if it does or does not
it's "wait for end of frame" right? but graphics might not be done by the time your frame is ended. meaning the picture that the gpu is rendering isn't finished rendering at the end of the frame
so its kinda... a thread you launch to gpu?
you can
okay this iis gonna be harder than already was
async gpu readback means schedule this piece of code to run when the resource i'm rendering to has actually finished rendering. don't wait for the result this frame
ReadPixels explicitly waits for the rendering to complete
do you see what's interesting there? because until you ReadPixels
so i just need to use the async gpu readback on that operation?
unity knows you don't need the texture on the main thread
that's sort of what the error was saying
the error is horrible
if you just want to show the camera's output in your scene, put the render texture on a material
if you need to save it to disk
one is to use async gpu readback
which you're right is not supported on some low end devices
i wanted both
so i kinda have cached
yeah you can do both
the different areas
well... reading the texture from disk is always synchronous so it will lose more than you gain
because the player usually doesnt modify more than 2 areas at the same time
this is a unity limitation
i'm not sure if it's still a problem someone who has done this more recently will know
yeah but thats not too much of a problem, since i saved the texture without encode
the saving and reading is... 2 ms
maybe 3
2ms is 1/8th of 16ms 🙂
that's actually a colossal amount of time lol
as i saiid... when i change 'mode'
also for something that you don't really need to wait for
theres a transition, im kinda free to use some time there
okay
yeah this stuff is really tricky
yeah it also helps me looking up things too
i am also learning
basically the idea is you have a texture that only exists in the GPU's world, the render texture
reading the unity docs about asyncGPUReadback
on a mobile device, it's unified memory. however, i don't believe ther'es a way to ask unity to "demote" a render texture to a regular texture
it's possible that asyncgpureadback can do that for you
i also don't believe you can mark a render texture as read-only after it's been drawn to. after all, the camera will be writing to it next frame
this means that, overall, you have a pretty problematic situation
you will have to copy in order to cache something to disk from the gpu, if you are also rendering to that same piece of memory later
you can create a pool of render textures
16 rendertextures
you would need a pool of Nx16 render textures
or use exclusively async gpu readback and create a copy (i.e. ReadPixels)
it actually must already give you a copy
yeah it does
async gpu readback gives you a copy
a texture is just "a view into a gpu resource, potentially unintialized"
async gpu readback will initialize it for you
resource to read the data from.... ah i guess thats thew render texture what you give to the asyncGPU
yes
so internally async gpu readback does
var source = renderTexture.GetNativeTexturePointer();
var destination = destinationTexture.GetNativeTexturePointer();
CurrentGPUCommandBuffer.afterRenderCommands.CopyFromToWithCallback(source, destination, AsyncGpuReadbackCallback);
bilit means copy in graphics?
yeah
okay im gonna give a try to this
the idea is that the gpu command buffer, it's like a Task that is run on the "gfx" thread
and you're adding more stuff to run at the end of the task
does that make sense?
and "gfx" tasks are ALWAYS DoGfxTask().Forget() 🙂
it's always UniTask.Void.
yes, and before this i was doing it in the CPU
but then... shoulnt unity have a more straightforward way to do this kind of stuff?
it is unknowable how someone will use the texture
some people use the textures for gameplay
i mean.... i understand this now you explained but... everybody using ReadPixels will be wasting resources if doesnt know this
ah
ah of course, the main difference here is as you said... i was waiting for something i was not even going to use
shit this took me on a wrong day
lol
😅
yes everybody using readpixels is wasting resources
i agree
unless it is important for the business logic of your game
almost everyone will want to reference the render texture in their material
ill try to improve this shit and let you know how it goes
or use async gpu readback to do work on a rendered frame in unity
if you need to do work on a rendered frame that is exclusively graphics, usually it's best to use a custom pass / full screen shader
if you need some hybrid of all of them, you can use jobs*
buff... im not ready for that shit, im the only programmer in the project and i have my hands full
jobs that use managed types are not compiled with burst. so for example the job that splits the rendered texture into 16 pieces would be a burst-compiled job, then the 16 jobs that save those buffers to files would be a not-burst compiled job
and the dependency chain for jobs is explicit. what that means is you can expressly state if you need the output of a job on the main thread for gameplay purposes
the way you do that is INCREDIBLY ARCANE because i believe like many things in unity (i'm looking at you UGUI) it was written by ESL people, which as an ESL person i do not mean disrespectfully at all
i am saying that to just illustrate that jobs are helpful, and the way its APIs are named is bad, but they are the right APIs
burst compiled = fast
yeah yeah im grateful for it
but if im not wrong... in order to work with jobs i need to pass raw data to the job, cant use textures or unityEngine stuff right?
you would use uni task for saving to files, btw, since it would be blocked by file io which is already pipelined elsewhere
sorry im not into it at all so know little about it
but writeAllbytes is async
sorry
im using
stream.WriteAsync
speaking of Job limitations
for some reason I assumed you're not supposed to access unity's APIs from them, but just randomly tried using Debug.Draw and it worked just fine
did I assume wrong ? would like to get a clear list of do and don't for jobs, so far I only know about unmanaged memory and native containers
my understanding for job system was - just do a lot of parallel math and data manipulation
but seems like you can do more with them ?
you can only burst compile and therefore accelerate jobs authored within specific constraints
if you ignore those constraints random bad things will happen
yes this is what i understood
oh yeah i found that not long ago! gonna take a look
observe read pixels is not used!!
yeah, so far, all my jobs should be fully burst compatible
I would just like to offload more stuff into jobs if that's possible, and I'd like to know what you should not do inside jobs
all these api calls set up a "job" (not in the sense jobs) with a dependncy graph to be sent to the GPU
i.e. a command buffer
that changes all the time
and i've NEVER authored a job
I see, so I should research every single thing before moving it inside a job
im trying to understand the script
any1 knows if this is upToDate
if no, then whats the new version called
can you have a mesh with multiple submeshes all using the same material ? can't find anything that would suggest that possibility in the docs.
alternatively, if I add the same material multiple times over, so that each submesh has one, will that save draw calls at all ? (I'm looking into implementing a mesh combiner to optimize rendering performance and to reduce gameobject count)
from the looks of it, seems like you're supposed to merge all the submeshes, and then, if the combined mesh needs to be modified - reassemble the whole mesh again with modified data. is my assumption correct ?
okay so that did work thanks
my initial idea was to combine meshes into a single mesh so that each submesh would have its own submesh index, which I wanted to use to try and set an empty triangle list for that particular submesh
situation => highest performance option
when it's the same mesh duplicated multiple times with the same material => gpu instancing
when it's different meshes with the same material and the meshes don't move relative to each other => use static ("static batching") it will combine them for you
when it's the same mesh with different materials => you're boned
Only in NetworkBehaviour classes, and you should not be using UNet at all
if you are using HDRP, gpu instancing is the only way in practice to avoid 1 draw call per object. hdrp you'll see has a huge number of draw calls
"you should not be using UNet at all" why is that?
It's literally deprecated
Replaced by Netcode for GameObjects
why? because hdrp supports lots of realtime shadows is my understanding
@rugged radish so it can be really scene specific
Not supported anymore
if you want to reduce draw calls in hdrp, the highest yield thing you can do is manage your lighting & shadows really tightly
then gpu instancing
because every hdrp material basically has "shadow map" as a hidden parameter
and you can see how the same mesh and the same material can have different shadow maps depending on where it is in the scene
As I said, it was replaced with Netcode for GameObjects, use that or another solution like Photon PUN or Mirror
I need to reread about GPU instancing, because I can't remember why I opted to go for mech combining approach
it can even foil gpu instancing is i guess my point
i am using mirror
that's also why shadow atlas size is important
im wathcing a guide that uses mirror
cuz i dont know how this networking stuff works
Well you need to be using Mirror not using UnityEngine.Networking
it lets you do 1 shadow texture for everything and kill draw calls
there's a lot of details here
thanks!
what kind of scene is it @rugged radish ?
i'm jk
Mirror obviously
it's mirror
you're at the start of a very long journey @haughty niche
Just Mirror
maybe start with a Photon sample
okay thank you!
the main issue I have are the trees
there's just too many of them, so I need to both, improve rendering and CPU (reduce the number of game objects)
yes hahah, my friend got so mage rage over all shooters and said "damn i really want a shooter without recoil"
so here i am XD
trying my dear life
to make a shooter
im not fluent nor do i understand programming at all
but i have a map and working controls for a player
just need to get the networking down
You're in for a bad time
it's a bird eye view, camera is high above the ground and looks down
and im set (for now)
and I can't just paint trees like foliage, they do behave like game objects, player will often remove them
still does not work
if i recall you have a LOT of trees
it looked like a forestry simulator
doctor do you know?
yeah, it's a lot even in a single world fragment
so it's probably too late for this
but the best thing to do is to have a LOD=0 tree that is identical everywhere, that is used for gpu instancing
for some LODs 0...N you use the same handful of tree models and materials. if they are only illuminated by the 1 directional light in real time, they will be correctly instanced (by LOD)
the thing that is "different" about each tree can either be baked into the whole tree (so gpu instancing "draw call" per unique tree) or you can split it off into different pieces
As I said, it needs to be a NetworkBehaviour class
where LOD 0...N is invisible, and N...max_lod is the unique elements
this is my second day of unity and c# where would i type that?
im sorry if i sound stupid hahha
You ought to not be doing this at all
You are in for a horrific time
well im doing this for my friend so i want to try
some things that will blow up efficiencies gained by gpu instancing -> trees that can cast shadows on other trees
im gonna give up when i cant to more
think about how that would work
but im going as far as i can
Well my advice is to learn C# first
It's a start
someone who is really a rendering expert can say if that happens or not
You need to learn C#
insted of mono?
@rugged radish what rendering pipeline do you use?
i am only really familiar with HDRP
damn, I know very little about GPU instancing, just glanced over a summary, so I need to reread that again to see if it's applicable to my situation
what
URP, want to target veeeery average devices
where should i put the thing that you wrote to me?
It's not a hard concept to grasp, you don't know C# and you are trying to implement multiplayer, not a good combo
i think if you want to see any of the effects of your choices, first you have to measure without shadows
@rugged radish shadows basically complicates everything
there's a lot of shadows, but I'm actually going for a stylized look, I suspect it can allow a lot of simplifications
i believe hdrp actually correctly gpu instances in 1 pass to generate the shadow atlas, then renders with it later in another pass
so that's fine
if it's one directional light you will not have problems with gpu instancing
i remember your screenshots
you should definitely be using gpu instancing
you will probably want https://docs.unity3d.com/Manual/SRPBatcher.html#intentionally-removing-compatibility
to force the trees to be rendered using gpu instancing
@undone coral i kinda made it work on the first attempt!
Yeah, reading the docs rn, I do have some requirements.
I think I turned away from GPU instancing because I assumed it's not a good fit for interactive elements
but maybe I just assumed wrong
you would GPU instance your LOD 0...N-1 where N is your "interactive" lod
does that make sense?
yes you probably want to put writeallbytes on a unitask thread
and then you're gucci
and do using _buffer so that you correctly handle io exceptions like running out of space
or iunvalid permissions
now i dont need a texture anymore, except whenever i want to load this on the material
(you should probably panic for those anyway)
oh yeah
you have to use LODs
it's unavoidable
you don't have to change the scripts to be aware of LODs
shit im so happy, ill let you know how the global process goes and send you the script if you want
I think I do, but still, need to have a better picture of the GPU instancing first 👍
LODs aren't really a problem, it's all programmer art anyway
throwaways
it's just the technique to control what has to look unique versus can be a generic tree
@rugged radish https://player.appmana.com/watch/wendysbasketball <-try shooting basketballs into the seats in back
there are 1,100 of them visible and gpu instancing made it run extremely efficiently
nice stuff btw
didn't know you could do something like that, have normal lods and a special instanced lod on the same model
@undone coral so basically what we do here is send the task we were doing with the cpu before with readpixels to the GPU? is this correct?
well... what you did was unblock a pipeline of rendering commands
hold on let me show you a screenshot
sure