#archived-code-advanced
1 messages ยท Page 69 of 1
IDK seems really overcomplicated. I would have just done this:
private int FacingSign => (int)Mathf.Sign(transform.forward.z);
What does this code do?
it checks if you're facing forward or back
if you want left/right then it's private int FacingSign => (int)Mathf.Sign(transform.forward.x);
ok thanks
When I use this line of code:
private int FacingSign => return (int) Mathf.Sign(transform.forward.x)
I get the following error "The type or namespace transform could not be found"
'Cowboy.Sign(transform.forward.x)' must declare a body because it is not marked abstract, extern, or partial
- the other code you had also used
transformso I can only assume you didn't put this code in a MonoBehaviour if it's complaining about that. - get rid of
return(that typo was my bad)
also you're missing a semicolon... not seeming very #archived-code-advanced right now tbh
Ok thanks
Im sorry if this isnt in the right section, I wasnt sure where this would go. Im trying to enter play mode faster, and Ive already messed with the enter play mode settings. My scene has a fairly large object pool, but other than that its basically empty.
Why is unity calling SaveScene() everytime I enter playmode? I already saved my game, I dont need it to do that. Can I turn this off? I have failed to find any information about how to control this or why its even called when I press play.
I think it's gotta save so the scene editor is synced with playmode
I dont think I understand why it would need to sync the two though, as no changes are really made during play mode and everything should be pre-set for testing via the editor
I don't think saving a non-dirty project should have any impact either though
Im hoping im wrong with this, but I ran into an answer on Unity:
https://issuetracker.unity3d.com/issues/editor-unselects-elements-when-entering-and-then-exiting-the-play-mode
One of these edge cases is with prefab instances, which were not getting fully backed up to disk even though they were dirty. This mistake was causing them to be different when coming back out of playmode, and also causing their selected state to not be properly restored.
Unfortunately, for historical design reasons that we are now somewhat stuck with, this optimization cannot work robustly, so we have decided to remove it.```
If im understanding this correctly, it sounds like.. I cant avoid it? As unity used to actual have a ignore save button..
anyone know why my shader produces no color whatsoever? It seems makes the entire image invisible
Shader "Unlit/test" {
Properties{
_MainTex("Main Texture", 2D) = "white" {}
}
SubShader
{
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
https://discord.com/channels/489222168727519232/1128942517023416370
Anyone have experience with downloading ASTC or DTX files instead of png?
why texture = ((DownloadHandlerTexture)request.downloadHandler)?.texture; returns me null even if data is not null and it is correct ASTC image?
nope, looks alright..
I ended up using shader graph but I'm still not sure why that shader makes the tile map transparent
How should I do packet delta compression when player position data is sent to clients via UDP?
So far I am thinking of creating custom packet for each client per tick of all player positions (delta compressed)
But that is O(n^2) operation and with just 32 players would result in 1024 iterations per tick (timed and on my pc it is about 2ms per tick)
Currently my code is something like (called every tick and is Unreliable packet)
void SendPositionUpdateOfAllPlayers()
{
// create message
// add every players' position to the message
// send the message to all clients
}
This works fine except I don't want to send non changing state of players or projectiles.
Should I use job system with burst for this or would it even work with riptide (to build messages in jobs)
Or maybe send states as reliable packet every second and send deltas relative to that (simple approach but doesn't yield as great bandwidht savings)?
whats the best way to make manual animator transition?
think of it transition without condition in animator. animator will play animation automatically after end reached or sometime before it
how about sending only and only when needed
you might have a situation where player isnt in your view
server or p2p implementation?
Dedicated server
Each input packet, the client should tell the server the last state he received
and the server computes the delta based off of that.
You'll need to variable width encode your values, and quantize your floating points before packing the data together.
You can use a bit flag to denote whether a state has changed or not.
that's about all there is to it.
@plush hare thanks. However what im worried about is iterating players with O(n^2) complexity per tick to build the delta compressed packets
Test it in a build. Not in the editor.
Your game server should only be running one core anyways, so jobs is of no use
if you're lucky, burst will SIMD your stuff. Otherwise you'll be writing your own AVX2 parallelized code
Assuming 32 players
thats too much time for 32 players. you're making a mistake somewhere
Alright I will debug
actually depending on the CPU, that might be a reasonable time frame. It's 4 in the morning and my brain isn't working rn
30hz should give you about 33ms per tick
again, your server should only be running one core per instance. Sometimes it hurts performance to try to parallelize everything on to different cores
Yeah I was hoping that burst could optimize the nested loops
The only real recommendation I can give right now is to just make sure you've got nice linear data
minimize cache misses
make it nice and predictable for the hardware prefetcher
Okok
posted in the vfx channel, but maybe someone here will recognize what it might be? #โจโvfx-and-particles message
@plush hare Appreciate the help. Not sure what I was doing earlier, now I'm getting now about 0,15ms per tick
What's the best place to talk about packages?
I created a custom package that I can download from GitHub into my project using the package manager (which I'm super pleased with) but I want to make custom classes in my actual project that inherit from one of the base classes in the package, yet it won't recognise the namespace so I can't reference those scripts in my project.
Thoughts on how to deal with this?
You got to create an AsmDef and reference the one in your package
Stop cross posting...
I'll check that later. I'm sure I did that and it didn't work, but I might have misremembered
Then your class has to be private otherwise it would work
coming from a programming background I spent way too much time trying to figure out a good way to do something instead of just making a game... I implemented a state machine using components subclassing monobehaviour, and when switching states I just set enabled = false on the prev state, and enabled = true on the new one. Instead of abstract state enter and state exit behaviours I just use onenabled and ondisabled.. is tnere anything wrong with this approach?
If it works, it works
the only wrong thing about it is that if your fsm is nested it will receive its parents OnEnable/OnDisable
to it wont have a true "state enter" event
A simple switch statement and an enum is more lightweight. Unless your state machine is complex it might not be worthwhile to build out a class structure like that, and will probably be less performant.
If by on-x you mean using event subroutines, they can be tricky and extra work if you want your events to play nice with a Task based Async architecture (the default eventargs stuff doesn't/can't run async)
Forces you to make your own type of async event args and async subroutine to bind to, it's a pain
i'm currently implementing A* on a grid based aproach. currently my system obtains the nearest available node from the start position and the world position by converting the world position to a grid cell
However, my code is a bit faulty, as it seems to be shifted a bit, i'm unsure what's causing the shifting itself
https://hastebin.com/share/jeturohuti.java
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
the hastebin itself contains what i've done so far, sure its a bit cut down to avoid sharing the entire class, but it should contain the general idea for it.
the issue is basically that the GetNodeIndexFromPos is nnnot really working as i expect it to, considering the fact that its shifted as the picture above shows
apologies if this isnt precisely the correct place to ask, i've never triedd to implement A* until recently and it seems a complex topic :b
Could you circle a "expected" vs "actual" in that pic
I have a 3D environment made out of runtime-generated thin-walled meshes, and I want an orthographic overhead view to display those walls as lines. I have a line renderer as a child of the meshes set to have points along the vertices of the mesh, set to only be visible to the overhead camera. This allows the overhead camera to see the "walls" with the line renderer despite them being vertical planes (First image shows this working as expected). This works fine for simple shapes like squares, but for more complicated shapes it forms a lattice of lines across the vertices (Second image). I want to only outline the "outside" of the mesh, but I can't use bounds because some of the meshes are angled or circular and a box is not always the best fit. How could I determine the outermost edge of vertices in a mesh to pass to the line renderer, or, barring that, is there another way I can display lines where flat vertical planes would be?
Will do, I'll just make the start and end gizmos the same color as the start and end transforms
Is it possible to hook into your runtime generated logic to keep track of walls at that point?
Or is it 3rd party?
They're generated in an entirely different program, saved as GLTF meshes, streamed to the project and loaded at runtime. I could make an additional mesh that just has the outlines, but that would be more data that has to pass between them
Prolly would be better performance at the cost of game size.
Aside from that, can you get the normals of the lines? A vertical polygon has a normal in the horizontal plane right, it's vert component should be zero
@lethal flint
https://i.gyazo.com/176310eb79bfc093e71d38aeeeed8c3f.mp4
here you go, the red represents the start, black represents the path while green represents the destination
here's a still pic with the grid itself showing, the white wireframes being the available grids for the algorithm
Looks like global vs local position issue, do they belong to a parent object perchance?
no, all objects are at the root of the hierarchy
Or the uh, whole grid object parent
Using the normal could work, it'd at least be better, but there might still be some internal geometry I don't need
sorry, the GameObject AStar has both components, the AStarNodeGrid and the Pathfinding System
while the End and Start game objects are the ones i'm using for testing purposes
doing a search of localPosition on my project doesnt reveal anything, so i doubt it's that specifically, might be with the method i wrote that should transform the world position to node index
Alright, quick one. is there any way to see what the full function name is there? this is in a profiler window which is zoomed in all the way, and I need to know what's getting called here
naturally I can't zoom in any more
you can switch to hierarchy view instead of the flame graph
Does clicking it help? Or hovering over it to show a tooltip?
No & No, unfortunately. Gonna see if I can find it now in the hierachy
I think you can right click and show it in the hierarchy, or select it and press a button somewhere
Hierachy doesn't have it, despite it being there in the Timeline view.
Right clicking is a solid nada here, not sure if I need to toggle something to allow that or not. this is in the standalone profiler.
What Unity version are you on?
2020.3.21f1, coworker found it on a previous frame. thanks for the help
fucking photon
Does anyone know why my the default custom unlit shader isnt working with tilemaps?
figured it out, it seems by default tile maps are facing backwards, thus you have to set shaders setting "Cull" to off
How is that even possible?
Im generating at most 25 objects
Funny, but every time I instantiate the object, its instantiates itself...causing the start to be called, causing more instantiating...
๐
Ah, recursion
wait, that shouldnt occur tho
because, Im not instantiating the hexgridmap object
If I instantiated the Hex shape in HexGridMap, should the instantiate call the Awake and Start methods in Hexgrid map?
how IJobEntity get nativeThreadIndex
If the hex shape and hex grid map are in thesame object, instantiating the hex shape will also instantiate all components associated with the game object, just recalling the awake methods in said componenets
Probably passed to it when the job is started on one of the threads.
Hey, is there a way to draw a batch of Sprites in a performant way?
I need to have some graphical image between each tile division in a hexagonal tilemap, some sort of "wall", that may or may not appear depending on some gameplay rules.
I know this kinda sound vague but I looked at Graphics.DrawTexture but it doesn't seem to work on Update or take camera into account and I need something that can be zoomed in and out too. Did some research around and couldn't find a satisfying solution and I'm worried about spawning a hundred sprite renderers in a scene for a WebGL game.
are you doing something that breaks batching? That would be the easiest solution. If your image uses the same material and texture (or textures are packed into the same atlas), you can manipulate sprite geometry directly to avoid extra renderers
No i'm doing nothing out of the ordinary. Just read this and yeah, it's gonna be the same image and material, so apparently is fine.
https://docs.unity3d.com/Manual/DrawCallBatching.html
Hi! I am searching for a tutorial to make a dynamic blocking animation system for melee combat. I want the hand and the sword to be positioned according to the collision point, by using Two Bone IK Constraint and other dynamic bone components. Any recommendation or info about this context?
Where do people go to talk about unity's localization package?
Unity forum has a dedicated localization section. One of the Unity devs is quite active there.
Right, so I am doing some reflection for a editor tool, and running in to an issue with events.
There is an event that takes a internal class as a param. I need a property from that param class, and I need to be able to subscribe and unsubscibe. So I can't just use a lambda to 'convert' from one to another.
internal class UnityParameter
{
public int foo;
}
public class UnityClass
{
public void Register(Action<UnityParameter> action);
public void Unregister(Action<UnityParameter> action);
}
This is the method I want to add to pass as a parameter to the Register and Unrigster methods.
public void MyCallback(int bar);
Any ideas?
All that is coming to mind for me is to have a 'converter' method. And a static dictionary of Dictionary<UnityClass, Action<int>> which the converter method calls maybe. And I subscibe MyCallback to the action in the dictionary.
That feels really ugly, so I was hoping there would be a nicer way...
Generate some code that takes UnityParameter and casts it to object (or gets the field or w/e) and calls your function
Generate some code?
Linq.expressions for example
Ahhh
Shoot I gotta go re-re-re learn/brush up on expression trees, but that seems like a good way to do it! Thanks!
Yeah I remember seeing examples of it.
If you got until monday I can send you a similar example ๐
I just don't use them enough, so how exactly to build one starts to slip my mind.
Depends on if I can figure it out or not depends if I have until monday ๐
๐
All this just to support SerializedProperty array binding in UITk
Wait, wouldn't this have the same issue as a anonymous lambda where you couldn't unsubscribe it?
Uhh
You might be able to get a methodInfo from it and assign that
and use that to unassign as well
Hmm, I think that would be the same thing
Tbh, I'm not sure on the details of assign events reflection
You can always set it to null
Well it isn't an event event. It is the UITK visualElement.RegisterCallback method
How the event is exposed if UnityParameter is internal ?
Oh right
It is actually a visualElement.RegisterCallback which is generic and takes anything that inherits from EventBase<T>. And one of the subclasses (SerializedPropertyBindEvent) is internal
You are trying to directly register to a SerializedPropertyBindEvent event which has a T of UnityParameter ?
No, this is what I am trying to do. But SerializedPropertyBindEvent is internal
visualElement.RegisterCallback(MyMethod);
public void MyMethod(SerializedPropertyBindEvent evt)
{
}
Maybe you could somehow instantiate a System.Action<UnityParameter> with Activator.CreateInstance through getting the type by Reflection.
Then, the issue is that you cannot declare public void MyMethod(SerializedPropertyBindEvent evt) ?
You cast pointer of function to other type.
Yes sort of. The event has a SerializedProperty Property { get; } which I want to access, so I still need it, or I guess, need the value from it.
I guess I could do void MyMethod(object evt) instead. But that passes the responsibility of getting the property off to the method itself.
This would be what I would try.
With the use of maybe Convert.ChangeType.
Basically I want to create a extension method void RegisterPropertyCallback(this VisualElement element, Action<SerializedProperty> callback)
You can define the extension itself ? What is public void MyMethod(SerializedPropertyBindEvent evt) in relation to this extension ?
That is not possible due to SerializedPropertyBindEvent being internal. So I would change it to public void MyMethod(SerializedProperty property) and pass it to the extension method as the callback
So you want to convert public void MyMethod(SerializedProperty property) to something like public void MyMethod(SerializedPropertyBindEvent evt)
While SerializedProperty is a field of SerializedPropertyBindEvent
Other way around
internal class SerializedPropertyBindEvent
{
public SerializedProperty Property {get;}
}
This is not possible as SerializedPropertyBindEvent is internal.
visualElement.RegisterCallback(MyMethod);
public void MyMethod(SerializedPropertyBindEvent evt) { }
So this is what I want to do.
visualElement.RegisterPropertyCallback(MyMethod);
public void MyMethod(SerializedProperty property) { }
public static void RegisterPropertyCallback(this VisualElement element, Action<SerializedProperty> callback)
{
// Somehow register the `callback` to the `RegisterCallback` and get the `Property` value from `SerializedPropertyBindEvent`
}
I'll look at it latter if you want to continue the conversation.
Sure thing, thanks
I've been trying to use a compute buffer in a URP render pass for a while, but no matter what, it always generates a memory leak, or other problems, no matter how I use it. (For reference, the buffer is of a fixed size, known at compile time) Instanciating in the pass constructor, and destroying it when the parent render feature's Dispose() method seems to leak (why?). Creating the buffer in the OnCameraSetup() method, and subsequently destroying it every frame in OnCameraCleanup() doesn't leak at least, but the created buffer doesn't seem to function (why?)
Is there any advice on how to go about this?
It seems to me that you want three things.
1- Create a System.Action<SerializedPropertyBindEvent> that invoke a Action<SerializedProperty> with the property inside the Action<SerializedProperty>.
2- Register the newly created System.Action in RegisterCallback(System.Action<SerializedPropertyBindEvent>);
3- Have the capacity to unregister the previously registred event.
For the first part, I believe you can simply create the required System.Action through the usage of Reflection with Delegate.CreateDelegate. There is multiple example online that seem plausible that could potentially be adapted to your need.
The second part should be pretty easy if you have a little knowledge about Reflection.
For the 3rd part, you will need to either use a Dictionary to hold the conversion between Action<SerializedProperty> and System.Action<SerializedPropertyBindEvent> or return an object to represent the newly created derived which you would be able to use to unregister.
class Program
{
public static void Perform<T>(T value)
{
Console.WriteLine("Called = " + value);
}
public static Delegate CreateAction(Type type)
{
var methodInfo = typeof (Program).GetMethod("Perform").MakeGenericMethod(type);
var actionT = typeof (Action<>).MakeGenericType(type);
return Delegate.CreateDelegate(actionT, methodInfo);
}
static void Main(string[] args)
{
CreateAction(typeof (int)).DynamicInvoke(5);
Console.ReadLine();
}
}
https://stackoverflow.com/questions/12131301/how-can-i-dynamically-create-an-actiont-at-runtime
haha funny enough that is actually what I was asking if there was a way to avoid (the dictionary I mean)
I've little to no experience with URP Render Pass, however everything that I have done seem to work correctly. I've follow tutorial and use the open source code to found out my way.
I do not think you can avoid it. Except if you use a return object.
Thanks, good to know I was right that if I wanna unregister the only way really is to use a dictionary to store them.
If you find a way to map System.Action<SerializedPropertyBindEvent> into Action<SerializedProperty> directly without instancing an intermediate you could, however I doubt it is possible.
Yeah, too bad you can't do like an implicit conversion for delegates like you can for structs and classes. Guess that would feel a bit cursed though haha
Maybe the dynamic keyword could be use there. I've yet to experience the full capacity of the this particular keyword.
Yeah nor have I, though it could be a possability
Implicit conversion would not necessary help here because you would need to instantiate a new value to convert one from an other.
Ahh you're right, I would need compile time access to the internal SerializedPropertyBindEvent
is there a difference in using actions in a list, or defining a delegate to fire?
Are there significant things I should be aware of?```cs
namespace Utils
{
public class Timer
{
private float _currentTime = 0;
private float _maxTime = 0;
private List<Action> _actions = new();
public Timer(float time, Action a)
{
_actions.Add(a);
_maxTime = time;
}
public Timer(float time, Action[] a)
{
_actions.AddRange(a);
_maxTime = time;
}
public void Tick()
{
_currentTime += Time.deltaTime;
if (_currentTime > _maxTime)
{
_actions.ForEach(x => x.Invoke());
_currentTime = 0;
}
}
}
}
No need for a List. A single Action variable should be subscribable as a multicast delegate, in just the same way you'd subscribe to an event
ie _action += MyMethod
I may have completely glossed over event registrations on actions. that saves me quite a bit of overhead
much appreciated
if only there was a way I didnt need to use Update to make it tick xd ```cs
public class TimerController : MonoBehaviour
{
private List<Timer> _timers = new();
private void Update()
{
foreach (var timer in _timers)
{
timer.Tick();
}
}
}
altho tbh, one update loop for all my timers isnt too bad
Yeah, one update loop is not bad. I wouldn't get worried about the overhead of using Update unless you've got 100+ gameobjects in the scene using it at a time, in which case it's time to use some sort of manager for it
some form of frustum culling based update checker might not be bad ๐ค
make a scene updater behaviour that updates a bunch of others from its Update, based on if they are visible in the camera.
can reduce everything into a single update loop haha
actually, that sounds like an interesting idea, albeit heavily scope creeping
Just because things are off-screen doesn't usually mean you don't want them to do anything
true
Hello guys. I dunno why I get this error message from my unity project. Each time I install the 2D package in my project, the burst one make this error message
@urban warren whats your end goal for your efforts above? It sort of looks like you are trying to do Event Delegation
@onyx blade you can also use Asynk or Coroutine instead of Update. And also you can do not call it each frame it is to expensive. You can call it each millisecond for example.
wouldnt calling it in update be more efficient than every millisecond given update runs dependent on the framerate?
or am I missunderstanding something here?
To add a callback to the SerializedPropertyBindEvent event
I do understand the use of the coroutine here, as I can just infinite loop a coroutine and work from there
with the whole WaitForSeconds logic
Ye, do infinite loop as coroutine or as Async but maybe update is the same result.
iirc, a coroutine has an update loop going on in the background.
dont quote me on that tho
I vaguely recall reading about that somewhere
"wouldnt calling it in update be more efficient than every millisecond given update runs dependent on the framerate?" about this one
ah
Did you read my answer I deleted?
yeah i did
nice sry I typed message then acsidantely delet it
no worries
I think Update the same as Looped Asynk or Corroutine you can use any option.
I also do kinda think im getting into optimization that may be irrelevant. still good to know.
but the difference in performance is most likely negligable, especially for my usecase.
im not planning to have 500 timers xd
if I have like 10, I tihnk I just about covered things
Async functions can't call Unity API, so they're not a replacement for Update, and Coroutines run every frame so are no performance improvement (and they also have a tendency to make code messier)
Don't make up performance issues. Unity provides you with the best profiler in the industry. Identify bottlenecks through profiling, then address those.
The idea isn't to make a game that maximizes performance, the idea is to finish a game...if you waste all your time blindly looking for things to micro-optimize, you will not release
just to be more specific, it's being off the main thread which is not allowed for most of the Unity API.
Async can be used fine if you use UniTask (package) or Awaitable: https://docs.unity3d.com/2023.1/Documentation/ScriptReference/Awaitable.html
this one hurts me, I havent finished a game in ages
for exactly this reason, and the reason that I suck at doing art and need to rely on others that may or may not help
Yeah, it's easy to get caught up in, premature optimization can lead you down interesting roads, it's easy to put in weeks of work only to realize you've gained just a few milliseconds
That said, shameless self-plug, here's my solution so people don't have to go down that path with Update:
when people ask me what I do, I used to say game developer. now I say tool developer most of the time.
I build tools I will need to make a game, and never finish the game
it's not shameless if it's relevant IMO
Damn, 6 years ago, I need to update that repo
im just gonna star that for later, I dont need it (yet) but it is VERY interesting
I must say @sly stag im a big fan of your website xd
Thank you! The design was fun to put together
time for my own shameless plug! https://torbenvanassche.dev/
Like idle animations and walking animations
Fancy!
the dog is an actual native 3D element btw! not a game engine of any kind ๐
You've posted the same question in 3 channels now. Don't do that, stick to #๐ปโcode-beginner
My questions is getting flooded by the guy with the mw2 pfp
And you're breaking the server rules
<@&502884371011731486> Shitposting
well, meme gifs*
Are you serious rn?
Why are you so serious
Yeah not sure how that gif went through
No gif here lol, have you actually read the rules?
I mean you broke two in less than a minute, so that probably means no
@fresh salmon lets not feed the troll and let one of the mods handle the situation
@night drift Read the rules and quit spamming the channel
Does anyone know how to still help me tho?
In #๐โanimation probably
You don't do it all from the code. Setup an Animator controller with transitions and parameters, and control said parameters from the code
Haha
It looked like this
ok that was pretty funny ngl
Recording a video of yourself breaking the rules, very smart, especially when mods can see deleted messages
It was a GIF OF A CAT
Please
Ill leave this as soon as i fix my code
I simply want animations
Is this some sort of weak blackmail attempt?
FUCK
FUCK
Huh?
Go to #๐ปโcode-beginner
Adding animation to a script isn't an advanced issue
I did it
But i looked glitched asf
and the #๐ปโcode-beginner Channel is filled with the ghost mw2 dude
Repost later then
I was about to say, that doesn't really change the difficulty of your question
Yes
I want to copy pixel data from one texture to another.
But not in a rectangle area, but in a triangle. Any smart ideas for that? In Winforms i would use a GraphicsPath and in Halcon i would use a region to limit the domain, but Unity Texture2D does not have that. Anything similar?
do you know the points beforehand?
or is the Texture the only input
if you know the triangle's points, you can itterate the pixels and figure out where stuff is using the same principles for mesh collision detection ๐ค
if you dont know the points, I have nothing to offer.
but im very curious how to solve that
yeah that's kind of a nightmare to do, there are algorithms for looping over triangle areas in a 2D context, but nothing I know from the unity API.
I would think the only real way of doing it is to check if its inside the triangle or not and doing something based on that information. by simply checking the pixel coordinates in relation to the triangle
which, depending on the resolution of the texture, could be a fkn performance nightmare
you can speed this up a fair amount by using a triangle drawing algorithm, which are well established
so you only iterate the pixels you need
could you also um
generate a triangle mesh?
like
if you take the square you have and the triangle,
you could use the texture on a square.
if you then slice the the triangle from the square,
n the above case you would get 9 or so triangles.
then you search the vertices that are not part of the triangle and remove them
then you sample the triangle from the texture according to the UV's and the resulting texture is what you need
thats probably way roundabout of doing it, but im weirdly interested in seeing how that performs
I know the points. Its the triangles of a mesh.
triangle drawing algorithm is a great searchterm, thanks!
is there any quick and easy way to just show a small widget for each of these points for my script, in the editor? Just like a single dot or whatever should be plenty, at global world position
or is this better asked in #โ๏ธโeditor-extensions
you can use the OnDrawGizmos API for that
it has a function like start and update on monobehaviours, which you can use for editor only drawing of stuff
perfect, this looks exactly like what I need, thanks!
not a problem! I'm currently debating whether or not I need tk define a grid for my game or just manually place the tiles. considering they don't change placing them is fine, but it would be much easier to drag them into a grid they snap into or generate them via code...
Does this logic seem sane? I think its working
Dictionary<Vector3, HashSet<Vector3>> Waypoints = new();
private void TryAddWaypoint(in PolygonCollider2D collidor, in Vector2 from, in Vector2 to)
{
if (Waypoints[from].Contains(to))
return;
var closest = collidor.ClosestPoint(to);
if (!(to == closest))
return;
Waypoints[from].Add(to);
if (!Waypoints.ContainsKey(to))
Waypoints[to] = new();
TryAddWaypoint(collidor, to, to + Vector2.up);
TryAddWaypoint(collidor, to, to + Vector2.right);
TryAddWaypoint(collidor, to, to + Vector2.down);
TryAddWaypoint(collidor, to, to + Vector2.left);
}
trying to not only get all the points but track the connected From/To points as a dictionary of Point -> ConnectedPoints, should make doing the shortest path stuff easy later
oh man, I'm not the best at pathfinding... I bought an asset to specifically avoid having to do it xd
code above is purely just to pre-cache the list of all the points contained inside the collidor
and their points they connect to
ah shoot I need to do 8 directions not just 4
depends on if you need diagonals, but I assume so
yeh I do :x
TryAddWaypoint(collidor, to, to + Vector2.up);
TryAddWaypoint(collidor, to, to + Vector2.up + Vector2.right);
TryAddWaypoint(collidor, to, to + Vector2.right);
TryAddWaypoint(collidor, to, to + Vector2.down + Vector2.right);
TryAddWaypoint(collidor, to, to + Vector2.down);
TryAddWaypoint(collidor, to, to + Vector2.down + Vector2.left);
TryAddWaypoint(collidor, to, to + Vector2.left);
TryAddWaypoint(collidor, to, to + Vector2.up + Vector2.left);
that outta do er
yeah that looks like all 8
I think the initial logic looks fine at a glance, hard to tell from my phone to be certain tho
u might wanna check if the dict contains [from] at the beginning and create it if it doesnt, rather than doing the same on [to]. Otherwise when you call this initially, you might have to assign the first point manually
yeh just encountered that haha
Aight so I think I almost got this, but my value for a var I am storing the lines in for the gizmo to read off is is becoming null inside of OnDrawGizmoSelected
I currently just have it declared as a private variable on the class, do I need to apply an attribute to it or make it public or something so it actually persists? Im guessing atm its being treated as ephemeral by the scene editor
where are u assigning _lines? because if its on awake/start, itll just always be null until you play
inside of the Setter of Waypoints
Im seeing even Waypoints is considered null though using a complex getter/setter, lets see if I can just function with it being a normal public var and just calc the lines on draw
nah its still null
well when is waypoints being set
please dont share extremely cropped screenshots of code, it really shows nothing
its being set by an import script
SuperTiled2Unity has "post processor" scripts you can run to manipulate game objects, so I add this component to one of the output game objects and set Waypoints on it
I dunno if there is an easy way to make a Dictionary serializable in the editor but the data should be getting set, prior it was just a list and the list was populated post import in the scene editor
but it just gets set like so, pretty straightforward
var waypointComponent = grnd.GetComponent<WaypointData>();
waypointComponent ??= grnd.AddComponent<WaypointData>();
waypointComponent.Waypoints = Waypoints;
oh I think I have an idea of whats different, I think because Waypoints (local var) is declared in the scope of the Import script, its dereferencing once the import script finishes
I need to instead do this, to make a new list and fill it with the contents of the Import scripts one so it doesnt de-reference...
waypointComponent.Waypoints ??= new();
waypointComponent.Waypoints.Clear();
waypointComponent.Waypoints.AddRange(Waypoints);
nope nevermind that aint it, still null
you shouldnt use ?? on unity objects, check if its null with ==
https://docs.unity3d.com/ScriptReference/Object.html
This class doesn't support the null-conditional operator (?.) and the null-coalescing operator (??).
anywho
does the value need to be actually serializable for OnDrawGizmosSelected to use it, and if it isnt it is null in that context?
Cuz I did a test here and added a string field, and then I set it right after I set Waypoints in the same spot, and then hit a breakpoint inside of OnDrawGizmosSelected annnd...
the string (which is serializable and shows up in the editor) does have its value, but the Dictionary (which is not serialized and shown in the editor) is treated as null
so Im guessing I need a serialized one?
no OnDrawGizmosSelected has no requirement for the variables being serializable, your Waypoints is just null in the editor since no code like awake/start has ran
although you are just showing somewhat random snippets, its hard to help. I dont know your system so most of the code shown really means nothing to me, since i dont know when its ran
then why is DidIGetSet not null
because its set in inspector
it got set in the same way
var waypointComponent = grnd.GetComponent<WaypointData>();
if (waypointComponent == null)
waypointComponent = grnd.AddComponent<WaypointData>();
if (waypointComponent.Waypoints == null)
waypointComponent.Waypoints = new();
waypointComponent.Waypoints.Clear();
waypointComponent.Waypoints.AddRange(Waypoints);
waypointComponent.DidIGetSet = "Yes";
the fact DidIGetSet has a value of Yes there means this code did indeed succeed in setting it
My gut says this has to do with serialization or something, because thats the only difference I am seeing between the two
is it serialized in the inspector now?
it also was working earlier when Waypoints was a List<Vector2> and not a Dictionary<...>
And List is serializable but vanilla Dictionary is not
yee
so therefore its set in the inspector.
what do you mean here
public Dictionary<Vector3, Hashset<Vector3>> Waypoints = new Dictionary<Vector3, Hashset<Vector3>>();
then it wont be null, just empty.
Im not sure if unity will cache waypoints added at editor time to dictionary
Nope
correct, unity does not serialize Dictionary by default. there are assets that can do it (or fake it), but unity itself can not
yeah my assumption was because it wasnt serializable, it wasnt persisting to be seen by OnDrawGizmosSelected which seems to indeed be the case
not hard to fix though, just gotta use one of the SerializableDictionary extensions
Just populate the dictionary on initialization with Linq
nope, its not being "seen" by the event, it looks like it needs to be an actual serializable value that the editor understands for OnDrawGizmosSelected to persist it in that calling context
the issue isnt with it being serializable, its just that the data does not exist yet because your code hasnt ran.
notice in this example, i did not make my class serializable
Gizmos don't require any serializable data
you gave it a default value of not null
so of course it wont be null
make it null/empty by default and then set its value via an importer script
Can you post the full code? I'm curious why this is an issue
this code is being run inside of an importer script that builds the component during import of a custom asset (SuperTiled2Unity stuff)
var waypointComponent = grnd.GetComponent<WaypointData>();
if (waypointComponent == null)
waypointComponent = grnd.AddComponent<WaypointData>();
waypointComponent.Waypoints.Clear();
waypointComponent.Waypoints.AddRange(Waypoints);
waypointComponent.DidIGetSet = "Yes";
and then the component itself is literally just
public class WaypointData : MonoBehaviour
{
public Dictionary<Vector3, HashSet<Vector3>> Waypoints = new ();
public string DidIGetSet;
private void OnDrawGizmosSelected() { ... }
}
I had that before, if the importer code creates the dictionary, then its value is null inside of OnDrawGizmosSelected
if I default it to empty so I dont need to set it in the importer, it is en empty dict in OnDrawGizmosSelected
but interestingly enough, the value of .DidIGetSet does get set there and it is present inside of OnDrawGizmosSelected
only difference between the two is one is serializable and the other is not
I think youre right, it wont populate waypoints as it cant be serialized?
in AddRange(Waypoints); what is Waypoints in that context? KVPs?
yeah I just tested with a List<int> and that is also persisting correctly with the exact same code
only difference between the List and the Dict is one is serializable and the other is not
yes because unity saves its value in the inspector, so it is not empty/null. My example was pointing out that OnDrawGizmosSelected does not require the data to be serialized. The reason Waypoints is null is because its not saved by anything
Im pretty sure now if I just swap to a serializable dict this will start working
as that will save the values in the inspector, yes
but if you change something from Waypoints, you'll need to have it adjust the values in the inspector or the draw gizmos wont be updated since itll still be referencing that
aight, so far so good, but looks like collidor.ClosestPoint isnt working quite right D:
ah I think I see what is going on, its offset by a bit yeah, aight
Is 370 kb of data on a command buffer too much in unity?
Or would it be better to separate that into multiple command buffers?
I don't think spreading it over multiple buffers will help. How many commands are you putting into it?
Not sure, but many, It's a recursive function that assigns it, good thing, sometimes it weights 120Bytes, and sometimes 380Kb
A rough count, 1228 commands for weight around 31.6Kb
So, a rough count, for that picture I sent there might be around 14620 Commands
๐
Well, on the frame debugger I have this
for 31Kb
Hey @brisk spruce, Little late to the party but as someone who also had Waypoint related stuff in a dictionary I just wanted to +1 AYellowPaper's - Serialized Dictionary package (It's free). I've used a ton of third party implementations of serialized dictionaries ("Odin Inspector", "SerializeDictionary", "Serialized Dictionary Lite") but AYellowPaper's is by far the best experience i've had. Your mileage may vary though ๐
I'll check it out! What was the difference you found that made it stand out?
Other cheap or free versions just felt a little clunky with their inspector implementation and odin inspector's implementation doesn't support use in prefabs
I'm just getting started with DOTS, I created a subscene that has items on a little island in my scene, it is set to Auto Load, on startup the objects all appear, but I'm not seeing log messages from one of my scripts in the subscene (I am debugging why it isn't spawning a GameObject, so I added Debug.Log onto its Awake / Update methods, but not seeing anything). I'm sure I am doing something wrong, but I don't know what.
If I spawn several un-awaited Tasks to modify a list should I put locks on the list?
Is lock ever needed in Unity tbh?
Tasks dont need locking
but you should be awaiting the Task at some point somewhere
Forget what you know about gameobjects with DOTS, do everything in systems instead
Also #1062393052863414313
no await then it runs synchronously and you are read-write the list, you have to lock the critical section
Can you elaborate on why task won't need locking?
if you dont await it, it runs async but you drop all error logging and whatnot, the stack trace goes kapoof and really bad stuff happens if you drop the task itself before it complete due to exiting context
if it errors or breaks itll just silently fail
but it will still silently fail but in an async way XD
Yes I noticed this.
All errors are silent within unawaited tasks
fuckin magic, but uh, theres literature on it but effectively Microsoft has some very smart people that made a very smart API
and I have only the smallest inkling of why they magically "just work" and Ive been using them for years
but wouldn't the several tasks race against each other?
something something Task Manager Engine or whatever
theres a big giant invisible machine underneath the hood ensuring 2 tasks dont step on each others toes at any point
Ok, and it is not related to Unity's running everything on main thread?
unity doesnt run everything on a main thread, just uh, most of things
but as soon as you use Tasks (correctly), it is inherently auto-magically multithreaded
List<int> lst = new List<int>(){1,2,3,4};
async Task modifyLst() {
//remove first element
//add it to the back
}
void Start(){
_ = modifyLst();
_ = modifyLst();
}
So I am for sure getting 3, 4, 1, 2 in this case?
nope itll be a race condition
no
itll be a race condition for which fires first but each task doesnt have any awaits in them, so youll still have them do their individual tasks one then the other
i have said you are read-writing the list and you havent await (wait until previous one finish)
that is intended
so your end result will be the same, but which one did the first step and which did the second technically is a race condition but its very likely to be A then B
ok I see, that makes sense.
the reason is purely because you're function is Idempotent
yes
such that A then B produces same result as B then A
if however you modified it slightly to have this:
async Task modifyLst() {
//remove first element
// wait 1 second
//add it to the back
}
then you'll have a variety of results
the execution order maybe first task remove first->interrupt->second task remove then insert->first task insert
wait 1 second as in thread.sleep?
await Task.Delay(1000)
dont use thread.sleep for Task stuff, really dont need to use it at all anymore, Tasks and coroutines replace thread stuff
ok so if you delay, then task now can interleave with each other, correct?
actually i believe even you await 1000 the result is still random the interrupt maybe occur before the first one remove
and anything you can await counts here
but didn't Pixxel say that interruption is not possible without a await in the task itself?
an async method without any awaits just compiles to run synchronously
oh yea ture
youll notice in Visual Studio if you have async but no awaits within, it greys out and gets underlined as a warning
For context I am spawning four players in a for loop.
Don't really care who spawns first, but I do use four unawaited tasks to spawn them, instead of awaiting one to spawn then spawn another. Task has await inside because it needs to load addressables etc.
But inside the spawning task I do have to access a common resource (list of spawnpoints).
That's why I asked.
if you wait 1 sec before removing or after adding to back result is still deterministic, yes?
yeah that would make it Idempotent again
what about nested tasks. Is result still deterministic?
My understanding is yes, because the two runs of ModifyLst still cannot interleave.
List<int> lst = new List<int>(){1,2,3,4};
async Task ModifyLst() {
//remove first element
//add it to the back
}
async Task Wrap(){
return await ModifyLst();
}
void Start(){
_ = Wrap();
_ = Wrap();
}
You need to await every Task object you create
else you are going to eat any exception that gets thrown in one
oh i mess up, task without await will run senquentially
yeah the crux of it is there is no await happening between
//remove first element
and
//add it to the back
so they will always run back to back without an interrupt
what should I do if I just want to run something in the background without caring about its outcome, also don't want it block main thread? In that case I always use unawaited Task and coroutines
use async void
but you also need to actually put the Task on a thread unless what you are waiting does that already
because it won't do that on its own
coroutines are meant for that, I think coroutines still keep their errors and stack trace intact
do coroutines keep their stack trace/errors intact? async void drops everything and messes up your stack trace something fierce, makes debugging and break points faceplant
Async void works fine in Unity
Any exception thrown in one is thrown to the Unity runtime and logged as usual
Outside of Unity I would not advise it
can coroutine do Task.WhenAll(
No
spawn that many coroutines, then?
but if a function is async void then you cannot await it at all.
That's fine for fire-and-forget only (which is what I asked for) but I sometimes do want to await for them and I dont want to make a second async Taskfucntion with exact same code
Honestly both seem equally annoying but what can you do, such is the life of coroutines :x
can just wrap it in async void wrapper 1 liner
async void MyMethodCoroutine(params) => await MeMethodNormal(params)
yeah I usually would go MyMethod, MyMethodAsync
yeah Probably yes yes
(it's sometimes a practice to append Async to every task-producing method)
yeah dereferencing a Task can cause bad things to happen, better to async void wrapper it
Spooky Garbage Collection At A Distance
Just to confirm, if you
void Start(){
DoTask(2);
Debug.Log(1);
}
async void DoTask(int val) => await DoTaskAsync(val);
async Task DoTaskAsync(int val) {
await Task.Delay(1000);
Debug.Log(val);
}
Will always get 1 then 2?
async void called this way won't be blocking right?
Yeah but it's not recommended since it'll swallow exceptions
I thought async void won't swallow exeception, and exception swallow happens only when you dont await a Task?
nvm, it does still swallow exception
then there is no point to use async void wrapper
_ = DoTaskAsync() does the same thing
Yeah it's the Task that contains info on whether an exception was thrown. No Task, no report
any exception in the DoTaskAsync above will be handled as a top level, unhandled exception by unity, the exception only gets swallowed if DoTask were to return a Task an that task was not awaited
Do you mean the async void DoTask(int val) => await DoTaskAsync(val); won't actually swallow?
I gave it a shot and it seems it still swallows exception.
Might be a Unity quirk, but in a regular app, DoTask swallows as it can't be awaited
yes, it only works because unity catches everything
it leads to people writing terrible async code just because it works in unity and never learn to do it properly
if you want to write somewhat proper async in Unity (that makes the hackery explicit), use UniTask
No I am saying it WILL swallow
public class Test : MonoBehaviour {
void Start () {
try {
Debug.Log ( "START" );
DoTask ( 2 );
Debug.Log ( "START AFTER DO" );
}
catch ( Exception e ) {
Debug.Log ( e.Message, this );
}
}
async void DoTask ( int i ) {
await DoTaskAsync ( i );
throw new Exception ( "DoTask EXCEPTION" );
}
async Task DoTaskAsync ( int i ) {
Debug.Log ( $"TASK PRE DELAY {i} {Time.frameCount}" );
await Task.Delay ( 100 );
Debug.Log ( $"TASK POST DELAY {i} {Time.frameCount}" );
throw new Exception ( "DoTaskAsync EXCEPTION" );
}
void Update () {
Debug.Log ( $"UPDATE {Time.frameCount}" );
}
}
the exception in async void DoTask is swallowed, the exception inside DoTaskAsync is not
Why the try catch?
to show that you cannot catch it
also how does UniTask help with excpetion handling in this case?
I am acutally using it, but it feels more like a better syntax sugar for me which makes a lot more thing await-able (e.g. a coroutine)
Itโs has unitaskvoid to explicitly express fire and forget so you never have to use plain void
in a Team with people of different expertise regarding async it makes it much easier to write proper code
Thank you ๐
I think the exception in async void DoTask is not swallowed but we just never reach that line because of the previous exception in DoTaskAsync?
Hi there, is anyone around for me to bounce a quick question off of?
I would really appreciate any insight you guys&girls might have, but I don't want to paste a giant script into here.
Edit: Here we go. https://hatebin.com/yusrlqlvuv
I'm working on a procedural generation script for a game i'm working on, and I'm having issues generating my roads.
๐ Large Code Blocks
Large code blocks should be posted as links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/
https://paste.myst.rs/, https://hastebin.com/
๐ Inline Code
Surround code with three backquotes. Not quotation marks.
To get C# formatting the first line should only contain cs or csharp.
Add a comment with a line number if there is an error message.
```cs
// Your code here
```
Do not share screenshots of code unless requested.
Hey guys, I need help with C# Attributes
true, ๐
When creating complex assembly hierarchies, I usually see people nest script folders within one another as shown in the image on the left with their asmdefs kind of all over the place really because of the structuring. Is there any problem creating assembly hierarchies as shown in the image on the right?
I just never see people use the approach on the right and wondering does Unity have a problem with that way?
1- read https://dontasktoask.com/
2- post your question in #๐ปโcode-beginner as it sounds like a beginner level question
command line tool problems perhaps?
I have multiple singleton managers that serve for multiple interfaces.
For example, UpgradeManager handles some upgrade operations for "IUpgradeable"s. I am basically passing the IUpgradeable to the UpgradeManager. Upgrade method and doing the business there. I want to call the Upgrade method like an extension method for IUpgradeable but I also do not want to create static extension methods for each type of managers and interfaces that those managers serve.
I want to implement a generic solution using an attribute for these kind of methods. The attribute will get the target type from the first parameter of the method target type (for our example typeof(IUpgradeable)), then objects that inherits IUpgradeable interface will be able to call a method with same name (by probably using some Reflection) as the manager's one.
In summary, if the manager has a method like:
[MyAttribute]
DoSomething(ITargetType targetObject, int someParameter)
Then I want to be able to call like:
(myObject as ITargetType).DoSomething(5)
And it will work like as it was called like:
TheManager.instance.DoSomething(myObject , 5)
So I have a hex terrain grid. Each hex cell just samples a stepped height map to get the height. My issue is, I am trying to figure out which cell the mouse is over.
My thinking was to get a ScreenToWorld raycast against a ground Plane at 0 facing up, that way I have a start and end point. Get all of the cells along the ray (from the ray origin to the point on the plane). And I thought I could just test the height of the cell vs the height of the ray at that position. But that doesn't really work intuitively, and getting the height of the ray at a point is kind of a pain.
So I was wondering if anyone had thoughts of how I could approach it differently. I guess I could make a hex mesh collider, and move it to each cell and raycast against it. But that feels really ugly to me.
You should be able to get the click position at a height of 0 and then use math to figure out which hex that click would be in using only the dimensions of the hexes and your mouse x,y
I don't know the formula for hexes, but the same concept as if you were trying to work out the cell for a click on a grid, but obviously the formula for a hex will be a little longer
I mean, that is what my thinking was. But struggling with how to get there.
Getting a cell at a position is easy if it is just a flat grid. But the height is what is messing me up
Here is a link to a graphing calculator to help you visualize what I'm talking about (I made it): https://www.desmos.com/calculator/ccxnopqqkr
Slide Hq and Hr to change the coordinates of the Red
Why does height come into it?
Because the cells are 3D?
Are you trying to align the hexes with terrain topology?
No, the hexes are the terrain topology. If you look at the screenshot you can see the terrain & hexes. I am trying to figure out which one the mouse is over.
I have a 2D logical hex grid, and then when I generate the terrain I use a height map to give each cell a height as well.
I think the approach of measuring ray height you mentioned can be tried. As you said, you raycast a plane and you can stop at the first "higher than the ray" you come across by running a while loop from the nearest to the farthest one among the hexes on the horizontal path.
Additionally, I don't know if this is less costly than using a hex collider. Seems like a lot of computation as you get farther away from the hex you're aiming for.
That approach kind of falls apart when the mouse is not over the top of a cell and instead the side. Maybe just moving a hex collider around would be the better solution. But it is just so much uglier for what is needed.
The easiest way, would be to simply add a collider on every tile. Depending, on your platform and type of game, I suggest you use that. It might be useful later. You always have the option to come back latter.
You can also use https://docs.unity3d.com/ScriptReference/RaycastCommand.html if performance is an issue.
I think for now I will just see if I can go with the collider that I move and test against. I don't really need colliders for anything else.
You might not need it at the moment, however it takes a lot less time to setup all collider and they might come useful later.
You are over-engineering.
Which is not a good thing.
It would probably take more work actually as I would need to handle instantiating and pooling them and updating their positions as the terrain is infinit. And right now I don't have any GOs actually spawning, just GPI instancing which later will be replaced with chunks of meshes probably
... I see that you have been over-engineering for a while.
Terrible habit.
Lol, well I don't think I am, but I'm open to suggestions if ya have them. The terrain/grid is infinite, and will probably use a dual grid for the actual mesh generation. In the game all you do is place tiles on cells, and sometimes the tiles affect the surrounding cells.
You do not need to create 1 mesh. You can use multiple mesh.
1 per hexagon.
That is what I am doing right now
Then, why you said you dont have GO ?
Because I am using GPU instancing
You can use GPU instancing on a material ?
Not exactly sure which type you are talking.
The Graphics command ?
What? Just like Graphics.RenderMeshInstanced(renderParams, _hexPillarMesh, 0, _pillarMatrixes);
Though I am having trouble figuring out how to set per instance data :/
You can simply use a material and mark it as instancing.
While having a standard renderer.
Also, I guess your game is gonna have a somehow isometric view or top down ?
Yeah top down, like a city builder type angle
Yeah, even more reason to not care about performance.
Top down game are hyper easy to optimize.
Because the camera is limited to the amount of things it see.
Personnaly, I would use a GameObject per tile with a collider.
Everything would be way simpler.
Huh, ya know I never realized that....
Give it a try.
In case you did not look at it yet.
Yeah I went and checked that my self just to see haha
Anyway, that will only work until I switch out for a generated mesh. Then I will just be using the GOs for the colliders
Why would you generate a mesh ?
Because otherwise I would need 6 Meshes for every hex. Are you familar with duel grid based mesh generation?
Not particularly
Nothing is coming up on my search.
Basically you have a second grid that is offset and you generate meshes from segments. It results in having smoother transitions and requires very few different meshes
https://twitter.com/OskSta/status/1448248658865049605
Like cube marching then.
Not exactly sure where is the issue though ?
Yeah similar
You have finite amount of mesh.
Which means a finite amount of instanced draw call
And you have a limited amount of object in view.
I do not think you would gain much with mesh generation in your context.
Yeah I'm just not sure at what point the trade off would be. Because if it is generated, you can collapse overlapping vertices, and have fewer meshes to draw. But could no longer use instancing. And with instancing you would have to render 6x the number of meshes per hex, but you can use instancing.
You are still over-engineering. Let's me ask you this: Do you need that ?
Is your game not gonna work/take too much performance because of that ?
What is "that" in this case?
Mesh generation.
How many draw call you expect without using any optimization ?
In other words, how many renderer in view you would have at a given time.
any way to extend AreaEffector2D so that it could selectively affect gameobject according to my custom rule (not just based on layer?)
Not 100% sure atm as I am still playing with the hex size/scale atm. But 200k+ maybe?
200k renderer ?
What are you doing lol.
1:1 earth ?
You gonna need more than mesh generation to be able to sustain something like that.
The amount of detail you would get with 200k renderer in view would be ridiculous.
200k cells. This is 287k cells render with the position gizmo being the center of the terrain/area
Not sure what you would call it really? To me this is still a 'top down game'. But sorry I wasn't clearer on the angle!
You can title/rotate the camera so it looks from a lower angle or from a higher angle, and zoom in/out
if you have a fixed perspective you probably want to have at least a few separate objects so the camera can cull most of them and save on tris
Having a fix angle make everything a LOT more easy to optimize.
Not a fixed angle unfortunately
Everything is dynamic (Remove tiles/add tiles) ?
No the terrain tiles/cells are static
or I guess better put, are not edited at runtime
So you would need to generate your mesh once ?
Infinite terrain though
Once per chunk
Yeah, it could be generated once and kept in memory
Though might need to dispose of them as the memory could get too large.
Mesh gen using burst and jobs is fast
So you'll only ever need to render this terrain and won't need to deal with collisions other than mouse clicking?
Relatively to CPU yes. It can be still a huge percentage of a frame.
Yuuup
I've seen games do mouse picking on the GPU. In fact, I believe Unity does that to know what you're clicking on in the scene (where not all meshes are guaranteed to have colliders).
I don't know what the go-to approach is, but a simple one would be to sample a depth texture of the scene at the mouse screen position, use that to convert to a world position and then you know exactly the world position the mouse is over.
It seem to me that if you intend to make such a huge terrain with the possibility of viewing everything you gonna need to integrate the notion of tessalation somewhere.
oooh, good thinking. I you could get a depth texture with just the terrain right? Though I guess just moving a single collider around would probably be easier to code up and maintain. At least for me.
I'm looking at the tiles in the back and my heart is crisping.
Possibly, not too sure how I would go about it. LODs might be enough. Right now it is taking about 24ms to render. And that is with an unoptimized mesh, and rendering all 6 sides of the mesh even if only the top is visible
How would you make your hexagon lower in in amount of vertices ? You would need to combine multiple hexagon together.
For a standard terrain, it is kinda easy. however for something like that it is going to be a pain in the ass.
Yeah, I mean if do mesh gen instead of instancing
I mean, you gonna need for sure to do Mesh Generation to be able to manage that much information.
I though you were doing a small top down city builder.
Maybe something like Civilization.
The big kicker is the the cell size. Civilization's is much large so that helps a lot. I mean I might end up clamping the view down a bit so you see less.
I mean, how would you sit a building on a cell that small.
Trees and stuffs, again, still working on the scale. I will probably make the cells 2 - 4x the size they are right now.
Also, the cell are gonna be really small to manipulate easily.
You see, this is WAY more managable.
And from this angle, you would be more than fine with renderer only.
You have what, 400 visible renderers ?
If we say that every tiles is 3 draw calls, that is 1200 draw calls which run on almost every PC.
This is what is right now for angle and 'gameplay'
I feel like it is unnecessary to add the possibility to change the pitch.
Maybe, but it feels nice to me and I like it when games have it. Though right now it probably goes down too far allowing you to see too far.
Anyway, if you have something close to what you are showing me. I feel that mesh generation is not necessary.
If it more in scope of what you were showing previously.
You gonna need to make a lot of optimization.
Yeah I will have to see how instancing handles it with more instances but less geometry when I am doing the duel grid gen
This is a perfect scenario for GPU mesh generation and rendering, because you only ever need to render it. The CPU doesn't need the mesh. Jobs and Burst are fast, but a GPU is bonkers. An RTX 3060 has 3584 freaking cores. No CPU comes close to that.
Ooooh, I totally forgot about Unity adding GPU support! I think the example repo that Aras made has some examples of doing it if memory serves.
GPU support to what?
For mesh gen?
Unless I am thinking of something different than you
You were planning on doing it on CPU O.o
Drawing procedural meshes on the GPU has been possible for a long time. Graphics.DrawProcedural has existed since Unity 5.2.
Oooh you mean that
I was thinking of the VertexBuffer stuff Unity added https://docs.unity3d.com/ScriptReference/Mesh.GetVertexBuffer.html
i have to ask is your performance really struggling with the stuff you have going on? it seems like a scene like this should still give you 300+ frames easily
unless youโre developing for mobile
Right now with about 100k cells it is taking around 4ms, though the WaitForPresentOnGfxThread takes 8ms sometimes. Not sure if that is directly related or not. Brings it down to about 50 FPS for me
That means the CPU is waiting for the GPU to finish.
So you're bottlenecked by the GPU.
Makes sense Probably RenderMeshInstanced I would imagine
aight, I think this seems like a very solid skeleton for the core of my game engine, anyone wanna give their 2 cents on it? Anything I should consider as a potential gotcha?
Game is a pseudo turn based system where everything occurs in "rounds", but the player input can queue up more than 1 "round" worth of stuff happening (IE if they click to move 3 squares, thats 3 rounds of stuff thatll happen back to back)
Can anyone help with gyro?
So it was working and doing that before
but now my remote might not be working, I unplugged and re plugged and checked in project setiings and iphone is still connected
at the start now it changes the cube to rotate a lil but for my phone its just not showing up, I also restarted the app and nothing
Thats what its doing now
Something with the remote 5 because I reopened and now my phone isnt showing up
sorry
Good:
- You have a separation between Input and Action which marvelous. It can look like a small things, however it really helps in the management of the flow of the game such as game state, player control, UI, etc.
- You attempted to manage the game with the StateMachine Pattern which can really help in game that are turn base.
- I see that you though of dividing the management of the action and the actual effect of the action.
Bad:
- The usage of Task seem to be a bit forced and out of place. The usually pattern I see is more close to having a "current" task which is update by function call instead of a literal Task.
- It is kinda hard to understand the purpose of
RoundEvent. It may be related to the fact that you seem to have a peculiar way of doing the "rounds". - The StateMachine Pattern is not correctly implemented. In fact, what you have done is closer to the Command Pattern.
In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time.
Neutrals:
- Your design of "rounds" is non-orthodox given that a single move is a full rounds worth. There is also the
RoundEventenum that is defined as a Bitmask and is pretty specific. - You are doing the
waterfallmethodology. It means that you design everything first, then you implement it all at the same time. This is not the most optimal strategy in the elaboration of any application or video game. Instead, you should opt for a methodology that build small iteration at a time. In your situation, that would be the implementation of a singleActionsuch as move (Selection of "Unit", Highlight of available displacement, etc.). There is no need for any architecture at this stage.
https://en.wikipedia.org/wiki/State_pattern
https://en.wikipedia.org/wiki/Command_pattern
how would I go about syncing a firing animation clip in my animator component to my weapon firerate?
You change the speed of the animation.
how would I go about that? I'm using a bool parameter, but im not sure if thats the best approach
{
WeaponAnimator.SetBool(_Shot, true);
}```
You would need to expose a parameter from the Animator directly.
Something like that.
here is my current parameter setup, not sure where to go with what you showed me
-
I am using Tasks to leverage IAsyncEnumerable and provide cascading support "downstream" in case anything lower in the tree needs to be properly async (IO ops and whatnot)
-
Rounds can have multiple queued up, a user can click to do multiple moves of rounds (ie click 3 tiles over), but I wanna be able to short-circuit out in case partway through something interrupts the queue (their character Encounters an object of interest part way through, triggers cutscene, gets threatened by an enemy). The RoundEvent has flags for these possibilities.
-
It will effectively be a StateMachine, the state machine parts just weren't included in the example there.
-
I already did a bunch of proof of concepts for individual pieces of my game, starting to bring things together now and this is the first big piece. I have a solid idea of all the pieces I intend to build.
im trying to find this, my animator setup in my inspector doesnt look like this
This is the inspector from an Animation State inside the Animator. (What I have shown)
mine looks like this
The upper part
This is a transition
You need to click on a state and look at the upper part*
ah now i see
- Overengineering. You can achieve whatever you are planning to do in simpler ways. Keep It Simple and Stupid (KISS).
- As far as I know, you do not need to have the concept at this level. You only need the concept of "interrupting". Also, the fact that it is a bitmask is strange and seem unnecessary. (I'm not asking you to explain it to me. I'm saying that the current way that you defined and named your structure (Notably the fact that it is a bitmask and that is not an Event) was not obvious for me. You take it how you want. Code should be self descriptive. )
- You should try to keep your StateMachine as a StateMachine and not merge it with other behavior.
- When I say iterative implementation, I do not say to do proof of concept, but literally build on top of previous iteration. The important is to always have something functional, take small steps to be able to rapidly come back if needed and then slowly refactor.
Overengineering. You can achieve whatever you are planning to do in simpler ways. Keep It Simple and Stupid (KISS).
I mean, if you have an alternative Id love to hear it, but this seems actually pretty simple to me actually. IAsyncEnumerable is pretty easy to use
As far as I know, you do not need to have the concept at this level. You only need the concept of "interrupting"
Well I need to know what kind of interruption it is, I may add further metadata to it but yes, thats the big thing about IAsyncEnumerable in modern C#, for all intents and purposes it is the successor to Events. Events are pretty terrible as soon as you want them to play nice with anything async (there's a reason you pretty much never see Tasks and Events working together at the same time, you cant+=Tasks together the way you expect Events to work. IAsyncEnumerable solves this.
You should try to keep your StateMachine as a StateMachine and not merge it with other behavior.
Im not. This is one of the 3-4 states of the game fundamentally (Menus, Cutscene, Ready, and Busy)
When I say iterative implementation, I do not say to do proof of concept, but literally build on top of previous iteration.
Honestly workflow wasnt something I wanted to chat about, Im familiar with waterfall, but I usually operate on much larger scales for my projects. A single sprint for me on my personal projects usually is on the scale of weeks to months, I have the time/energy for it.
... I should add a post to my blog demo'ing how largely speaking IAsyncEnumerable can just be a straight up replacement for Events, its largely the same principle but easier to work with, maintains stack traces better, and best of all it works with Async stuff inherently which is โค๏ธ
Not sure what is the point of IAsyncEnumerable if there is no code that will react to its returning value
Eh sort of, you still have the concept of "the pipe is now closed" but usually you can have some kind of useful output on the listening end. In my case my output from the pipe is the roundEvent I |= together
But if you are just trying to | (which look wrong in the code but I assume it's pseudo) it then it could be just Task<RoundEvent> and let the handler do | ๐
That would return a single event and not multiple
Task<RoundEvent> is to IAsyncEnumerable<RoundEvent> in the same way that RoundEvent is to IEnumerable<RoundEvent> in syncronous code
You can yield return and whatnot inside of IAsyncEnumerable methods
Events is actually a means of synchronisation between thread. Not sure what you mean by we never see Event and thread together. Event are not return values.
Your StateMachine contains directly the function PerformRounds which is not a responsibility of the state machine.
When I say KISS, I mean something like the following. There is no need for the usage of async process here as far as I understand the way your game works. (It might actually cause issue down the line)
private class PerformRoundsState : State {
private Queue<Action> actions;
private void Update(){
if(actions.Count == 0)
return;
if(!actions.Peek().Update()){
action.Dequeue();
}
}
}
and what do you do with current though
I know, I'm saying that you can just return RoundEvent.Okay | RoundEvent.Interest; instead of yield return each flags because it doesn't seem like you are doing something with that.
My bad, current is unused there.
Ah, but what if you want an actual count of how many things got returned?
There is probably a more elegant way of doing this.
Now you turned 2 things into 1, which can mess up your counts ๐
Why do you need that count for?
tracking expirations on stuff, etc, can be a wide variety of things.
Even just debugging, if Im wanting the 7th event, but the 4th and 5th event have been smooshed together by some called downstream, now my 7th is my 6th
but also yield return is just very nice to have overall, usually when you are Guard Clausing, yield return is slick
instead of
var myEvent = RoundEvent.None;
if (case)
myEvent |= RoundEvent.Okay;
if (case)
myEvent |= RoundEvent.Threaten;
if (case)
myEvent |= RoundEvent.Interest;
....
return myEvent;
You get this instead
if (case)
yield return RoundEvent.Okay;
if (case)
yield return RoundEvent.Threaten;
if (case)
yield return RoundEvent.Interest;
and thats it, done
Note how it removes your need to keep doing a "init a var, track it for the entire method, then finally return it at the very end" which gets very tiresome very quick for every single one of your implementations to be forced to do
Same reason why usually its a lot nicer to return an IEnumerable<T> instead of a List<T>, the latter you gotta new up a list, start filling it up, then return it at the end. Whereas the former you just yield return as you please and usually remove a few lines of code
I doubt that you'll need that for generalized code.
Also not sure with the intention of your Linq expression, probably SelectMany use case?
Which one?
This one
var handler = RoundHandlers
.Select(rh => rh.Run()).Aggregate((a,b) => a.Join(b));
Ah you cant SelectMany IAsyncEnumerables
in fact normally you cant even Join em but I have a specific extension method that handles that
Theres a very popular mainstream library though that lotsa of folks use that lets you get all your usual Linq stuff on IAsyncEnumerables, though the methods are all async as well of course
I only need Join though so I have just 1 file for that, I dont need the whole lib for it
IAsyncEnumerable ain't that bad, why is it overengineering? it's like IEnumerable but async. Would you call usage of IEnumerable overengineering?
Because there is no need of async.
hm well right no Linq ๐ but still, decent for plain iterations
Why would you turn something async if there is no need.
what gives you the impression there is no need
saying assuming there's a need, of course
as I stated earlier, I expect I have need of async there, IO operations and other such stuff
No need of async for IO and other stuff as well.
Sure, name Join was quite misleading to me when using within Linq
yeah I kept the linq method name still hehe, its pretty much the same principle, joins the two lists together but in a ~fancy~ way haha
Join should work like database join. I'd name it Concat
I believe thats Intersect for Linq IIRC?
that's partly true as well, but might not go along with all architectures. I'm fine with having some dispatcher when I need to sync to main thread, but some apps or orgs may not be
could complicate stuff a lot for junior devs as well
Intersect works like you're putting in HashSet one so bit different from Join
It is strange to complicated the whole architecture on the pretext of maybe one action will actually need async.
Im not sure why you think its complicated
I say that it is more complicated. Not complicated.
There is a difference.
I dont consider it more complicated either
the code doesnt change, even if it wasnt async Id still have pretty much the same code
I'm sorry, but this is a fact. If you can remove the usage of a whole concept it only make it simpler.
You ask opinion, and this what I think. If you do not need that stuff, do not put it there.
my await foreach would turn into .Aggregate() and thats.... about it
From my perspective, it is not needed.
and then Id have some fewer awaits in my code, and instead of Task id return void, aside from that, itd all be the exact same logic
However, I'm not the one making the game, I'm just speaking from what I saw.
I guess mostly when you talk about complicated, I view that through the lense of the actual logic.
Id be writing the exact same logic for all my code, Id just be yield returning to an IEnumerable instead of an IAsyncEnumerable
because I saved... five characters?
No, because you removed a whole dimension.
sorry, I just read the script. it's quite complicated if it just intends to process a turn ๐
Threading can cause issue.
process n turns, which many things can happen in 1 turn (every single entity that is active takes its turn simultaneously)
best scripts are simplest scripts -- try to read it as a junior, and count the WTFs ๐
Bad idea to have simultaneously turn.
thats how it is and how the game works
You gonna have a lot of issue with synchronisation and undefined behavior.
i may have missed it, but what does the async actually provide in the current implementation? Is this for performance
the actions that will occur for the turn are all pre-calced, that wont be an issue
How many action you intend to process ?
I get this, and if you intend to work alone that's totally fine! But if you intend to work with a team, might wanna consider how intuitive would be for more junior guys to process.
All depends on the context, of course. Code is code and as long as it works and won't shoot you in the foot later it's fair game and up to preference.
Personally some of my code is intentionally made complex and/or optimized for extensibility & performance. It's just the important high-level stuff I keep 100% clean.
I do find a lot of people struggle with Tasks and async stuff for awhile, its a bit of a different way to look at code, its one of those things that once you get comfortable with how they work, its not bad, but I wouldnt be writing stuff like this for a junior to consume from naw
There is a difference between struggle and keeping things simple.
You seem to take this the wrong way.
No people just genuingly struggle with Tasks and Async for awhile, Ive had to train plenty of em myself personally, its a bit to grok the whole concept of it when you are used to Synchronous code
Do you ever consider the fact that you may be over using Async and Task ?
Is it intended to be simultaneous? It looks half sequential ๐
they're pretty much the default now for modern asp.net stuff and whatnot
We are not in ASP.net environment.
I could not talk for ASP.net.
this part right here will fire off everything simultaneously unblocked
var handler = RoundHandlers
.Select(rh => rh.Run()).Aggregate((a, b) => a.Join(b));
However, as far, as I experienced Unity, I use rarely async.
It will start simultaneously, But it won't proceed after first yield until the loop consume the value
Nah they all run independently of each other writing to their pipes
oh sorry I see what you mean, mmm yes I think you are right? but the blocker is merely:
roundEvent |= roundEvent;
which wont exactly block for a notable amount of time
it should definitely be pulling off the pipe way faster than the pipe is getting filled up
The blocker is the other actions.
yield stops IAsyncEnumerator til Current is consumed
Oh you mean here?
foreach (var action in actions)
gotcha yeah, should be fine because as the pipe should always be close to, if not completely, empty
so it will write to the pipe and pretty much instantly get picked up and consumed
I think I see what your concern is, if I do like
foreach (var enemy in enemies) {
var roundEvent = await DoEnemyAction(enemy);
yield return roundEvent;
}
then I will end up still only processing enemies one at a time right?
Similar, but it's worse because it starts simultaneously at first but not after first yield ๐
yeh so, the trick is you actually would wanna do something like this
// ToList is actually important here to hydrate the tasks, I have learned this lesson the hard way before D:
var enemyTasks = enemies.Select(DoEnemyAction).ToList();
foreach (var enemyTask in enemyTasks) {
var roundEvent = await enemyTask;
yield return roundEvent;
}
psuedo code but yeah the key is to fire off the events together (if you wanna get fancy it can be good to batch em too, rather than just fire em all, sometimes), and then do your yield returns after you got everything spun up and going
Well yes for regular Task? But you now have IAsyncEnumerable involved
nah thats handled here:
yield return roundEvent;
Handler1() { await Task.Delay(100); }
Handler2() { yield return val1; await DoSomeWork(); }
In this case your Handler2 will not invoke DoSomeWork until Handler1 is done
Because val1 is not consumed
It's lazy evaluation
right, change Handler2 to this
Handler2() {
var workTask = DoSomeWork();
yield return val1;
await workTask;
}
make sure your tasks are spun up before you start yielding
Sounds bad, what if you have dependency between tasks? What if you need to yield return or yield break depending on task's return value? :/
what if you have dependency between tasks
Whats the issue?
What if you need to yield return or yield break depending on task's return value?
Still no issue, you canawaitbefore theyield, just know that any new tasks you spin up after ayieldcan be blocked
So you are using IAsyncEnumerable just to return value at the end? That sounds very error prone
you can return multiple, no issue
The main problem would be await's behavior will be different depending on where you put it (before yield or after)
Well Task's behavior to be specific
And that is very confusing
yeah its not await that you care about, its making a new Task
as long as you try to avoid, as much as possible, making new Tasks after the yield, itll work very smooth
personally I think something like this might be quite simpler, without any performance drawbacks:
public class TurnManager {
// ...
public void QueueAction(TurnAction action) { .. }
public void UnqueueAction(TurnAction action { .. }
public void EndTurn() {
var consumedActions = actions.Where(x => x.turnID == currentTurnID);
onTurnEnd?.Invoke(consumedActions, onTurnStart);
actions.RemoveRange(consumedActions);
}
}
public class TurnProcessor {
public TurnProcessor() { TurnManager.instance.onTurnEnd += ProcessTurn; }
async void ProcessTurn(IEnumerable<TurnAction> turnActions, System.Action callback) {
// potentially filter or sort actions. e.g based on initiative etc.
foreach (var action in turnActions) { // could even 'try to perform' them in parallel and process the results on main thread (e.g.: anims)
if (!await action.TryPerform(out var result)) { ProcessResult(result); }
}
callback?.Invoke();
}
}
You can't expect everyone would understand and follow that, If it is just your personal project then well you do what you want
yeah, they already said it wouldn't be for the eyes of juniors, but I agree it's not great to complicate core stuff like turn processing right off the bat ๐
you should also take in account you'll need to process stuff like animations, position changes, and UI in main thread anyway, and as it is, everything would have to be called on main thread (including IO)
I personally find IAsyncEnumerable great, but it might be a bit overkill for this considering it needs boilerplate to make functional ๐
so I just checked this here, doesnt seem to be the case unless I missed something
Test your C# code online with .NET Fiddle code editor.
actually since I cant see the console live, maybe it is the case, lemme retest but on my own machine to see if it actually halts and then spits all 10 out at once
nope no problem, the longer Task.Await doesnt block the other enumerable at all
it should work because linq does lazy evaluation
What do you mean? which line of code?
var handler = RoundHandlers
.Select(rh => rh.Run()).Aggregate((a,b) => a.Join(b));
// Process all the events and aggregate them into a single flagged enum
await foreach(var e in handler)
roundEvent |= roundEvent;
your code should work because linq does lazy evaluation, so nothing is populated or aggregated until you actually iterate on handlers (for which you use await)
but actually might have to do .Select(async rh => await rh.Run()) or smth xD
.Aggregate wont be lazy, thats a greedy linq function, it hydrates the query ๐
really ๐
its like .Max, .Min, and .Sum and etc
yeh, cuz it returns just a T, not an IEnumerable
its just a fancy .Sum function when you gotta do something fancier than just A+B
this might be a problem then ๐ rh.Run() should be executing async code
it does :3
We are aggregating effectively a list of Tasks, not the results of the tasks
its uh, a sort of fancy .SelectMany for Tasks, for all intents and purposes
I see your Join is not just Concat so yeah then it's fine. I'd say it is doing quite inefficient operations, but that's different argument.
Ive tested it under some hefty loads, it doesnt seem to have much overhead, a little bit but an acceptable amount for my purposes
I could write a better version that actually can take multiple AsyncEnumerables, rather than repeatedly combining A+B=C, C+D=E, E+F=G, but instead just do A+B+C+D+E+F=G
Yeah, I guess it is more of Rx Merge
Busy = true;
var roundEvent = RoundEvent.None;
var handlers = RoundHandlers.Select(rh => rh.Run()).ToArray();
// Aggregate all AsyncEnumerables together
var handler = IAsyncEnumerableExtensions.Concact(handlers);
// Process all the events and aggregate them into a single flagged enum
await foreach (var e in handler)
roundEvent |= roundEvent;
return roundEvent;
Aight, now it looks a little bit cleaner :3
riight, so it would need to be rh.Run()() to execute the actual async code, mb
nah .Run() returns an IAsyncEnumerable
Honestly maybe I should call the method .SelectMany lol, thats the closest to what it is for Linq
Im turning
IEnumerable<IAsyncEnumerable<T>> into IAsyncEnumerable<T> effectively
Should be roundEvent |= e ?
oh nice catch thanks!
Im surprised that VS didnt highlight the fact I wasnt using e there O_o
I think it should be called Merge, pretty much https://github.com/dotnet/reactive/blob/main/Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Merge.cs
can someone help me with this, I have a point (red one) on a slope and another one at the same height (blue one) how do I calculate the third point's (yellow one) position if i only know the position of red and blue dot and have the surface normal of the slope, im working in 3 dimensions
Use Vector3.Dot to project the Red/Blue vector on the Red/Anypoint point on vector.
Oh nvm, that would give you an other point.
you mean something like this
You might want to use trigonemetry here.
tried it, but it doesn't provide correct results
Function I did the other day.
private static bool IntersectLineLine(Vector3 lineAPositionA, Vector3 lineAPositionB, Vector3 B, out Vector3 result)
{
Vector3 A = lineAPositionB - lineAPositionA;
float AMagnitude = A.magnitude;
float BMagnitude = B.magnitude;
if (BMagnitude == 0 || AMagnitude == 0)
{
result = Vector3.zero;
return false;
}
float dot = Vector3.Dot(A, B) / (AMagnitude * BMagnitude);
if (dot == 0)
{
result = Vector3.zero;
return false;
}
result = lineAPositionA + B.normalized * (AMagnitude / dot);
return true;
}
Not exactly sure of the validity, I did not use it a lot.
I'm trying to boxcast the position for the feet ik system and the boxcast hit point is not at the same xz position as the legIK, and im trying to add or remove the needed height for it to be on the ground
Can you just raycast under the feet ?
no, beacuze raycast checks a single point and there might be nothing under that point
You can use boxcast or sphere cast also.
i do
wait a sec
do you see the problem, the sphere on the right is the hit position of the boxcast
i am aplying a correct feet height offset
Yeah, this is usually why you use raycast directly.
and this happesn with raycasts
Not really an issue.
?
(or just do 2 raycasts)
I mean, you do not need to solve it at 100%.
You could always fall back to boxcat if raycast fail.
that can cause twiching if im not mistaken
The argument of ray/boxcast is pretty useless since it won't change the fact that it's not working for them
I was just pointing out something. I'm not forcing anything here.
This is what I have done and it was working pretty well.
raycast are just not a good option rn
I have been hammering at this issue for the past 2 days so I'm really clueless
If you use Vector3.up always you can simply take the point at the location on your vector.
can you explain that a bit?
Let's say your blue dot is (X,Y,Z), then find the coordinate on the vector at (X, ?, Z)
the vector from red to the yellow dot?
Yeah
you are right only Y is changed
but how do i find it
also take note that the slope I drew is actually a plane
Let's say that you have a vector that has the point (A,B,C) and the direction (X, Y, Z).
You can define the equation of the line by:
x - A = X * t
y - B = Y * t
z - C = Z * t
You can find t by using x - A = X * t or any other equation that you know the coordinate.
I'll try this, thanks
You could also use trigo. (The law of sin)
x, y, z are the variable.
in the equation you have x and t as a variable.
It would be the position of your Vector3.up.
Vector3 slopeNormal = hit.normal;
Vector3 HitPoint = hit.point;
Vector3 PointToProject = leg_transform.position;
this is all the info I have
You could also just do intersection line/line I gave you earlier.
Even better intersection plane line.
im affraid that is a bit more than i can understand
private static bool LinePlaneIntersection(Vector3 linePositionA, Vector3 linePositionB, Vector3 planePositionA, Vector3 planePositionB, Vector3 planePositionC, out Vector3 result)
{
Vector3 P01 = planePositionB - planePositionA;
Vector3 P02 = planePositionC - planePositionA;
Vector3 P03 = planePositionC - planePositionB;
Vector3 IAB = linePositionB - linePositionA;
float sqrMagnitudeIAB = IAB.sqrMagnitude;
Vector3 normal = Vector3.Cross(P01, P02);
float denominator = Vector3.Dot(-IAB, normal);
if (Mathf.Abs(denominator) < 0.001f) { result = new Vector3(); return false; }
result = linePositionA + IAB * Vector3.Dot(Vector3.Cross(P01, P02), linePositionA - planePositionA) / denominator;
return true;
}
@dusty glacier
Even better, just use: https://docs.unity3d.com/ScriptReference/Plane.Raycast.html
wait that might be excatly what im looking for
You could even use directly the general equation of a plane given that you know X, and Z.
normal.x * (rigidbody.x - point.x) + normal.y * (y - point.y) + normal.z * (rigidbody.z - point.z) = 0
y = (- normal.x * (rigidbody.x - point.x) - normal.z * (rigidbody.z - point.z) - normal.y * point.y) / normal.y
using the plane raycast still gives wrong results
hit is the hit information of the boxcast it is marked as a white sphere in the first image
'leg_transform.position' is marked as the white box
Why you do not directly use hitPoint ?
it applies some movement on the x or z axis and the leg starts flying around
and still produces incorrect results
To be honest, I feel that it is what you do with the result that is wrong.
Can you put a gizmo where the point is ?
The point you are trying to find
So the point is correct
Or is it not align with the other one ?
it should be right below the box
What is transform.leg at this heigh ?
in line with it on global Y axis
something is wrong
as soon as the angle of the plane changes from 0 the position of the leg snaps to something else
Put two gizmo
.
the leg transform is the white box
hit point is the sphere
they are not in line as they should be
Pretty sure there is something wrong in your entry data.
Try it in a more isolate environment.
Hi
hold on
hi
I want to render a mesh at local position 0, any idea why this wouldn't render it?
var param = new RenderParams(GrassMaterial);
Graphics.RenderMesh(in param, GrassMeshes[0], 0, Matrix4x4.Translate(Vector3.zero));
GrassMeshes[0] is just a mesh, trying to bug fix and getting to the root of the problem
Nvm, it was working, I just couldn't find it
Hlo guys, I am working on a top down shooter game. It's my first game that i probably will get finished. I want to figure out how do i add recoil and make a modular gun script
You were absolutley right, the way i added feet offset messed with everything
thanks for the help, in the end i used the sin method
damn that hurts my foot lol
Question:
I'm creating a mesh and saving it via AssetDatabase.CreateAsset().
When i do that again and overwrite it, all existing references to that asset no longer work. (Missing mesh)
However: On a file level, it stays exactly the same. Same meta-file content, same guid, same file id. Nothing changed. I change the scriptableObject to reference the new asset and it is exactly the same as before.
Whats the correct way to overwrite Assets?
Not a bit of difference according to git. Mhhh
LoadAssetAtPath then modify the returned object
Then SetDirty & SaveAssets
Overwrite Asset, Open ScriptableObject -> Missing ( Mesh)
Overwrite Asset, Close Unity, Open Unity, Open ScriptableObject -> All good
why easy when it can be weird
Donโt overwrite
does unity have a way to combine IEnumerators together simultaneously for coroutines?
A sort of "When All" operator
(not just yield returning A then B then C, as my understanding is B wont start til A finishes)
or something like
yield return Coroutines.WhenAll(A, B, C)
Run them as independent coroutine and yield coroutine
what do you mean by the last part? yield coroutine?
Coroutine work1 = StartCoroutine(Work1());
Coroutine work2 = StartCoroutine(Work2());
yield return work1;
yield return work2;
I see, hmm, wish there was a way to combine em into 1 easily
I guess I could make a simple extension method
public static IEnumerator WhenAll(params IEnumerator[] coroutines)
{
foreach (var coroutine in coroutines)
yield return coroutine;
}
I've got a really bad memory leak that persists even when I end play mode.
It says to account for the 21gb leak I need to use a platform specific profiler? But I don't understand what it wants / how to do what it wants
That's different
Does that mean a platform built version with the profiler in it?
You need to StartCoroutine so it can run separately
You got issue with native object.
What is your platform ?
Windows 11
Then you should use Memory Profler that are specific for Windows.
You mean outside of unity or inside it? If inside it then I'm not sure how to get / use a windows specific one
I'm not exactly sure what to use with Windows Specific, however each platform, PS, Xbox, Android, IOS, Switch has their own profiler.
I would guess you should look what tool there is with Visual Studio.
Also, you can simply guess what your issue.
If your game is not large.
It's pretty early on right now but if the leak persists when not in play mode then it's an issue with the editor?
You should always profile builds*
There hasn't been a "build" yet
Unless you are just refering to build as the current version. It's not been built into an exe I mean
So from what I gather, I need to look into memory profilers in my IDE / Rider
Not necessary your IDE.
You should build it to be able to analyze correctly memory issue.
Otherwise you gonna have a lot of noise coming from the Editor.
I guess it makes sesne to do that first
right, hmm
the issue is you cant for sure say if you have already started the coroutine or not, I actually dislike that API
If I were you, I would look into: https://devblogs.microsoft.com/visualstudio/analyze-cpu-memory-while-debugging/
(I cannot guarantee you that it is what you need)
theoretically StartCoroutine should return something distinct from an IEnumerator
the fact that a started coroutine and a non started one cannot really be distinguished is sort of a problem, design wise
For the build I'm using Deep Profiling support and autoconnect profiler?
Not necessary.
if you get handed an IEnumerator, you dunno if its the coroutine itself, or the coroutine starter
Usually, you manage the logic with a wrapper. (Started or not Started)
