#archived-code-advanced
1 messages · Page 142 of 1
Yeah, I think writing good code is making it as obviously simple as possible, not flexing with obscure syntax or use.. there's always fun competitions and stuff for that (IOCCC)
Hey guys, I'm trying to make a spin wheel, but I want the arrow to stop at one of the four icons. Whats the best way to do this? Right now im just rotating the arrow for a random amount of time and then slowing it down.
Agree it comes off as a bit pretentious
A) Determine where you want to stop
B) Spin the wheel for a fixed amount of time
C) Tween the speed from 1.0 to 0.0 between the current direction and end direction
float speed = useWalk
? (useSprint
? (Input.GetButton(sprintButtonName)
? walkSpeed * sprintMultiplier
: walkSpeed)
: walkSpeed)
: (useSprint ? walkSpeed * sprintMultiplier
: 0f);
... that's really hard to mentally parse
@high lotus does this help?
int random = Random.Range(0,4);
float x = Mathf.Cos(((2 * Mathf.PI) / 4) * random);
float y = Mathf.Sin(((2 * Mathf.PI) / 4) * random);
Vector2 dialPosition = new Vector2(x, y);
It'll pick a random point from any of the 4 points in the circle
Forgot to add a radius but it gives you a vector in the range 0-1, if it needs to be bigger just multiply the vector
for a sphere use Random.onUnitSphere
He only has 4 points so not sure why you'd make it harder
just leaving that knowledge there because uniform randomness on the surface of a sphere is unintuitive, ive been told
Only thing random is one of those 4 points it can land on, again not sure why to make it harder than necessary
How do you move that dial right now
I guess if you use some kind of rotate function you can do something similar in degrees, like dividing 360 by 4 and then multiply that number with a number between 1 and 4. This will give you a rotation that always lands on 1 of the 4 spots
if (!finishedSpin)
{
spinwheelImage.transform.Rotate(0, 0, this.rotationSpeed * SpeedMultiplier * Time.deltaTime);
if (slowDown)
{
this.rotationSpeed *= 0.92f;
}
}
In update
Then it counts down between 2 and 4 seconds and slowDown becomes true
You could keep doing something like you're already doing, and just stop increasing the speed until it fully stops at a desired location
private void Resize()
{
Vector2 targetMotion;
Rigidbody2D targetRB;
if(target.TryGetComponent<Rigidbody2D>(out targetRB))
targetMotion = targetRB.velocity;
else if(target.parent.TryGetComponent<Rigidbody2D>(out targetRB))
targetMotion = targetRB.velocity;
else if(target.parent.TryGetComponent<Rigidbody2D>(out targetRB))
targetMotion = targetRB.velocity;
//for determining delta
float before = c.orthographicSize;
c.orthographicSize = Mathf.Lerp(c.orthographicSize,
Mathf.Lerp(minZoom, maxZoom, targetMotion.sqrMagnitude), zoomStrength * Time.deltaTime); //super smooth
float delta = c.orthographicSize - before;
//warning if camera zooms too fast
if(Mathf.Log(Mathf.Abs(delta)) > -2)
Debug.LogWarning("Camera changed size really quickly.");
}
why does it think targetMotion is an undefined local variable on the long line?
i defined it at the very top, so it should be in scope
It's declared but not defined--with your if statements, it doesn't appear to have a guaranteed value
If you have an else at the bottom, you could give it a default value (or before the ifs)
it all makes sense now, thanks
for some reason i thought structs got defaulted to a zero-like state
but thats just with fields
im so happy i got my moving platforms, character controller, and camera follow working absolutely perfectly
the character sticks to the platform perfectly
Thank you
Here's a more comprehendible version of my quadro-ternary
float speed = 0f;
if (useWalk)
{
if (useSprint)
{
if (Input.GetButton(sprintButtonName))
speed = walkSpeed * sprintMultiplier;
else
speed = walkSpeed;
}
else
speed = walkSpeed;
}
else if (useSprint)
speed = walkSpeed * sprintMultiplier;
else
speed = 0f;
If discord wouldn't auto tab stuff
you could simplify that
if (useWalk)
{
if (useSprint && Input.GetButton(sprintButtonName))
speed = walkSpeed * sprintMultiplier;
else
speed = walkSpeed;
}
else if (useSprint)
speed = walkSpeed * sprintMultiplier;
else
speed = 0f;
i think i can do even more
if (useSprint && Input.GetButton(sprintButtonName))
speed = walkSpeed * sprintMultiplier;
else if (useWalk)
speed = walkSpeed;
else
speed = 0f;
that makes sense to me
@native hinge
also you should create a sprint axis in the input config instead of hard-coding the name
I made a button called "Sprint"
and sprintButtonName == "Sprint"
ah
Anyway, there is only one problem with your simplification
If useWalk == false but useSprint == true I want the player to auto-sprint
In your case it stops movement
so the getbutton doesnt even matter
In that case, yes
if (useSprint)
speed = walkSpeed * sprintMultiplier;
else if (useWalk)
speed = walkSpeed;
else
speed = 0f;
Not quite what I meant
If you can both walk and sprint then the button must be held
If you can only sprint but not walk the button does not need to be held
if (useSprint && (Input.GetButton(sprintButtonName) || !useWalk))
speed = walkSpeed * sprintMultiplier;
else if (useWalk)
speed = walkSpeed;
else
speed = 0f;
like that?
Yeah I think that works
feel free to mess with it however works for you
i was just trying to show it should be possible to simplify
Mhm, thanks
It's true, but that's fine with me, it might be a little bit, I just want to get paid quickly. I think I was traumatized
I want to Invoke something from a abstract class anyone an idea how to do that?
What do you mean? Just invoke it like a normal method..?
Maybe invoke is no the thing i meant. I want to introduce delay time to a method so that it cant be spammed. But i cant use coroutines
You can if you get reference to a Mono ehavioe
Then you can use that to call StartCoroutine
Yeah but this would make my Statemachine to coplex im searching for a simple method
Without any context it's impossible to know what to do. There isn't a way to start a coroutine without a monobehavior (or maybe scriptable object) though
hmmm
You could do async maybe?
async?
I remember hearing that doesnt play nice (you can't use unity specific methods or something like that) though I could be wrong
No, you can. Or at least I haven't had problems yet using unity specific methods.
I've definitely used it for addressables so I think I'm. Missing context on where I hear that
Uhh i see. This could work i will give it a try, if not i will just make a coroutine helper and try to not overcomplexificate that Statemachine. Because i will have to run many coroutines
You can’t use most engine methods while not on the unity main thread… if you use async without Task.Run…. Your async method will stay on the main thread and unity api calls work
Ah, got it, that makes sense. I knew about the main thread thing, just didn't realize when async did/didn't run on the main thread. Makes sense why async works fine for me then when I have used it. Thank you for the additional info!
That was where I got that from then
I always though async was it's own thread though, how else does it not freeze the game with stuff like await
Also the unity synchronization context introduces a 1ms thread.sleep whenever an async „thing“ is scheduled I.e. when you await something. That can be a problem but depends on the project.
Btw, would you really need async for a state machine? Feels thatd be more event bases
Furthermore async allocates memory…. So those in terror of the GC don’t like it
Async has nothing to do with state machines
I mean in this user's question
They wanted something akin the coroutines for a statemachine
I actually found a way to fix my problem but its really messy and will make my code a lot longer. With some disgusting if statements
Tbh I try and avoid state machines for as long as I can. They spook me especially since the simple implementation is very ugly and the more complex one is - more complex to make
This one has very nice fluent interface and works for gameplay scripting just fine
I am making a state machine for my player and its quite useful for the many different movement types i am implementing
hi i have a for loop. going through 10 objects. i need an int to count up until half way through the count then start counting down.
so as the for loop i goes 0 1 2 3 4 5 6 7 8 9 the int goes 0 1 2 3 4 4 3 2 1 0
anyone know how to do that?
Probably a much cleaner way, but an If statement and book that is set when it reaches half way would do the trick
Though it doesn't sound very nice
for (int i = 0; i < length; i++)
int j = length - i - 1;
int k = (i < length / 2) ? i : j;
}```
One for loop, and another reverse for loop. Wow, easier to write, easier to read
thank you. it works
Do you know how it works?
works just as vertx said 😉
yes. i had somthing similar to the k part but the j is what i wasnt getting right
Just double checking. We are in #archived-code-advanced just want to make sure people aren't copy pasting stuff 🙂
that wasn't an advanced code question... was more like a leet code "very easy" question, kinda fizzbuzz level
Very much sounds like the kind of question that'd be on a bad quiz; which is why I generally would avoid answering them as given
good point
Anyone good in math and geometry to help me with something that might be easy, but i don't know the math to do what i want to do.
thing that i am doing, i'm placing two objects, then spawning a plane on the middle of both of them? (so far everything working like intended)
The object i'm spawning is a plane (as i am working on an AR app) the only thing is i would like the plane to be have it's rotations to make it be in the direction of the vector(just like if i was placing a wall), but i have no idea how to transform my vector dirrection into the rotation needed
if(placedObjects[0] && placedObjects[1]){
GameObject objectMiddle = GameObject.CreatePrimitive(PrimitiveType.Plane);
objectMiddle.transform.localScale = new Vector3(100, 100, 1);
objectMiddle.transform.LookAt((placedObjects[0].transform.position - placedObjects[1].transform.position));
Vector3 middlePosition = (placedObjects[0].transform.position+placedObjects[1].transform.position)/2;
objectMiddle.transform.position = middlePosition;
EventManager.TriggerEvent(ShelfPlaneHandlerData.SpawnPlaneHandler);
}
position it, then use LookAt. LookAt does not take a direction.
the fact is
Or use Quaternion.LookRotation, which does take directions
read what i said, i don't want it to look at something, that's not the question
You are so fast i had not even finished understanding the question wtf
a plane doesn't work with simple lookAt because its normal is Y (iirc)
the question is about the math
"i would like the plane to be have it's rotations to make it be in the direction of the vector(just like if i was placing a wall)"?
it's not difficult to understand
So how ur answer is solving the problem ?
You are using LookAt incorrectly. I've corrected your usage, and described another method to orient the plane that takes explicit vectors
that's on the last try, i wasn't using that before
but the fact is
the question is
How to convert a Vector dirrection to a vector of rotation
....
https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html you provide it a forward vector, and an optional upwards vector to hint at the orientation, and it returns a rotation built with those directions.
I'm trying it rn
but not sure it's gonna work
i'll keep u posted
not working
What is it doing?
Nothing els than it was previously doing
It will do different things depending on how your plane is configured. As Anikki said, planes usually have Y up, so you'll have to do some cross products to get the correct vectors
that's the thing i need, i am not that good in Math that's the issue
Quaternion.FromToRotation is your friend
Cross product returns a perpendicular vector from two input vectors https://docs.unity3d.com/ScriptReference/Vector3.Cross.html
FromToRotation could be a friend, but it doesn't well specify the other axes
you could just set Transform's up vector and do what FromToRotation does, as that's all up's setter does
// The green axis of the transform in world space.
public Vector3 up { ... set { rotation = Quaternion.FromToRotation(Vector3.up, value); } }```
ok
i'll try it
ok so i did a few test before trying to change
with this
i have something, but to make it good for me rn with that X scale of my object is Y scale and Z scale is X scale, and Y = Z
Ok it's good, i'll manage with that, Thanks anyway @austere jewel and @compact ingot for the help it was good documentations to use !
I've noticed that the elements of UnityEvents are re-orderable since Unity 2021. Does that mean the execution order is constant now, meaning from top to bottom? Or is that just a nice-to-have for designers?
https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/UnityEvent/UnityEvent/UnityEvent_4.cs Pretty sure it's always been
It just iterates through the call array and invokes them one by one
Oh, really? I've read on the forums that it dealt with delegates and its execution order was random.
That's great to hear!
Even if it was delegates it's not random
It's just not predictable in 100% of the scenarios
(while it should be in most iirc)
Hm. Gotcha.
I don't think Unity guarantees (i.e. in documentation) that they're executed sequentially but I doubt it'll change
Yeah
Don't crosspost
<@&502884371011731486> scam
Hello,
I'm trying to get the spot light in Unity to have no fall-off. I want it to illuminate objects the same amount no matter the distance.
As far as I understand, I need to write a custom shader for that?
Like a laser light? In a narrow band? Or still expanding like a cone?
Both works, whichever is easier
have you tried creating a spot light and adjusting the parameters to see if it matches what you want
yessir. so, for objects further than 5 units or so away, i need to increase the intensity a lot. and on that intensity everything closer is super bright. i tried setting the intensity by the distance of whatever we are aiming at, but it's also not very pretty because player can aim to something very far and the super intense light radius will happen to have a closer object on the edge
This also looks like it might be useful: https://docs.unity3d.com/Manual/ProgressiveLightmapper-CustomFallOff.html
As I understand this is for baked lights, I'm trying to have this behavior on realtime spotlight
hello. I'm trying to get inspector like rotations from code. I see that one quaternion can be equivalent to multiple euler angles, but my question is how do I get the closest euler angle to my current stored euler angle. Any tips? I want a method where I pass a quaternion and the current euler angles and it returns the euler angle values that are closest to the input
Vector3 GetClosestEuler(Quaternion quat, Vector3 currentEuler)
What do you need it for? Maybe there's a simpler solution than that?
I have an in game animation system and I need to auto key frame getting the euler values from the inspector
unity quaternion to euler conversion is quite bad for this usage
for example, 95, 0, 0 becomes 85, 180, 180
this will lead to a quite different rotation path than the desired
Can't you set the quaternion value directly?
Also, that example doesn't sound like a realistic scenario
I think quaternion to euler would always return the smallest possible value.
nevermind, you'd have to followed the path I followed to understand the problem
I guess this is a quite complex question for an internet forum
transform.eulerAngles ? https://docs.unity3d.com/ScriptReference/Transform-eulerAngles.html
transform.localEulerAngles should match the inspector
you can both get and set it
but if anything sets transform.rotation or localRotation, it will "mess up" the euler angles, in the sense that they get set automatically based on the quaternion (which is not a unique transformation)
try UnityEditor.TransformUtils.GetInspectorRotation(transform);
it would work, if it was not editor only
Perhaps you can look at what GetInspectorRotation does
more of a C# question here: how do I write a generic method that would accept a monobehaviour as parameter and then do something like if(GetComponent<T>()) GetComponent<T>().enabled = false;
you can add a condition for T, such as:
void EnableComponent<T>(GameObject obj) where T : MonoBehaviour { ...
use
bool TryGetComponent<T>(out T s);
you already have TryGetComponent
used like ```cs
if (TryGetComponent(out Script script)) {
script.Something();
}
Could you also do, GetComponent<Comp>()?.enabled = false
Can't test it right now so not sure
anyone used AnimationEvent.time in the past?
i'm getting some hasardous numbers with it, and i don't understand how to use it
it will end with this extern method, so it's not possible to read it
Shame. As you said it can be hard to ask these kinds of questions on Online Forums. Hope you figure it out.
thanks
Hey guys, Im making a damage indicator system that displays where the damage came from, and it all works besides the fact that it does not rotate with my mouse as I look at an enemy/source. If i move to the left of the enemy, it will rotate with movement correctly. It (the canvas element/damage indicator prefab) just does not rotate with my mouse. If anyone could help that'd be amazing, thanks! I also have the video I used to create it.
used it in one of the projects, what numbers are you getting?
i was getting 0.33 while in my Animation that it shows on top 0:10 when the first animationEvent is fired
i basically just want to normalize the value of animationEvent.time
Yes you gotta scale it
What's the speed set in the animator state?
For this animation?
1
Hm ok hold on let me open up that old project
Check what's your animationClip.length is saying. I don't remember the solution exactly but I can see that I was using this in my code
You are not setting events via code?
I have a list of 1mil gameObjects. Is this ok? Do I need to do it a different way to reference to them?
what does => (lamda i think?) do?
not really an "advanced" topic, but here's your answer:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-operator
im currently spawning game objects randomly on a space of 100 x 100 plane. however, nothing stops them currently from spawning ontop of another.
how would i keep track of what positions are taken and which isnt? should i keep some sort of 2d array holding x and y values and try to keep track like that? or is there any other recommended way
unless you have a non-recurring RNG, you will have to waste some cycles or memory on checking for duplicates
you could in theory make a list of all 10k positions, shuffle them, and take N.... those then won't have duplicates... but you need a (relative) lot of memory and cycles
dont use a 2d array btw... use a hashset, the array would be as "wasteful" as the shuffle method
Don't you hate it when you trip and fall into some corner of your codebase, and accidentally spend 3 days refactoring as a result?
best 3 days 😉
heh
it actually stemmed from a conversation in this channel, and I finally decided to do this refactor and.. obviously.. it was far bigger of a bite than i expected
but it's going to feel SO GOOD when it's done
// LCG that produces a full cycle of pseudo random numbers without any duplicates, see https://en.wikipedia.org/wiki/Linear_congruential_generator
uint seed = 0;
uint sampleSize = 10000;
uint generatedNumber = seed % sampleSize;
uint increment = 7; // coprime to sampleSize
for (uint i = 0; i < sampleSize; ++i)
{
generatedNumber = (generatedNumber + increment) % sampleSize;
}```
That's cool.
if you make a casino game with that, please tell me;-)
Without knowing Anikki's solution (which is kind of neat!), I would probably make a dictionary with a struct of x/y as the key and a bool as "is occupied" .. or if you need the opposite, a list of available locations with the same struct, and you get at a random index.
Yeah, it's clearly got some shortcomings, but for simple pRNG generation with some fixed criteria (non-repeating, true randomness not required, no moving elements) it's pretty cool
nothing like not compiling for two weeks, knowing exactly what you are doing and that it will work, and then it indeed does work
@carmine ermine I'm doing something like:
public GridPoint GetOpenSpot()
{
if (Items.Count == Width * Height) return null; // grid is full
// Enumerate available locations.
Dictionary<(int x, int y), GridPoint> availableLocations = new(Width * Height);
for (int rows = 0; rows < Height; rows++)
{
for (int cols = 0; cols < Width; cols++)
{
availableLocations.Add((cols, rows), new GridPoint(cols, rows)); //initialize
}
}
foreach (GridItem gi in Items.GetAllGridItemsList())
{
availableLocations.Remove((gi.X, gi.Y)); // remove filled squares
}
int random = NumberUtils.Next(availableLocations.Count); // 0 to count-1
int i = 0;
foreach (KeyValuePair<(int x, int y), GridPoint> openSpotKVP in availableLocations)
{
if (i == random)
return openSpotKVP.Value;
i++;
}
return null; //shouldn't be able to get here.
}
hehe
that's even only in one of my 3 applications, too
i did "complete" the server side of the refactor but who knows if it'll work yet 😛
this is very wasteful
Basically I was tired of debugging stateful desync issues so I decided to refactor the entire "battle" object that contains everything about a 1v1 battle so that it could be serialized, compared, cloned, and checked for differences
I'm looking for feedback on that, btw - I wrote that last night in a bit of a haze, and I hate it
(but it works)
I just don't see how it can be immediately/obviously improved, aside from writing it using linq (which isn't my strong suit)
if the method should only return one point, its extremely wasteful
yep, it only returns one point
thoughts on improving it?
public class GridPoint
{
[Key(0)] public int X;
[Key(1)] public int Y;
public GridPoint(int x, int y) { X = x; Y = y; }
}```
GridItem is a fairly bulky item that "exists" on a grid
you need to have a grid item for the entire grid i suppose?
No - a grid item is ... a thing, on the grid
think uh... merge dragons?
Grid items have a bunch of properties and stuff on them, but the grid itself is sparsely populated and items exist at a GridPoint (just a simple class with an x and y)
thank you guys! ill look into it
int random = NumberUtils.Next(availableLocations.Count); // 0 to count-1
int i = 0;
foreach (KeyValuePair<(int x, int y), GridPoint> openSpotKVP in availableLocations)
{
if (i == random)
return openSpotKVP.Value;
i++;
}
I think this is the most egregiously bad part of the above since this should be O(1) instead of worst case O(n) but I needed the dictionary for random access removal, and converting the dictionary to a list to get index-access to return that value would take best-case O(n) anyway
HashSet<Vector2Int> Items;
public GridPoint GetOpenSpot()
{
cellCount = Width * Height;
if (Items.Count == cellCount) return null; // grid is full
Vector2Int candiate;
for (int i = 0; i < 50; i++)
{
int random = NumberUtils.Next(cellCount);
int row = random / Width;
int col = random % Width;
candiate = new Vector2Int(col, row);
if (!Items.Contains(candidate))
return candiate;
}
return null;
}```
lemme digest, standby
erm, if I'm understanding that right, you're just attempting to get 50 random locations and then if it fails, return null?
if i understand that right - that can fail
depends on how dense you want to fill that grid
100% dense
then this is no good
🙂
the method should perhaps be named GetOpenSpotGuaranteed()
it only returns null if the grid is 100% dense
sec
np - appreciate it, btw!
would just keep that open list around ```cs
List<Vector2Int> Open;
public GridPoint GetOpenSpot()
{
if (Open == null)
{
Open = new List<Vector2Int>();
for (int i = 0; i < length; i++)
{
int random = LCG(Width * Height, i);
Open.Add(new Vector2Int(random % Width, random / Width));
}
Open.Shuffle();
}
return Open.RemoveAt(Open.Count - 1);
}```
hehe, unfortunately that's a bit difficult since then I'd have to keep that list in sync with the gameplay - grid items can move around
so now moving would require finding the open item in that list, removing it, and adding the from location, etc
it gets complicated since there's lots of game actions that can bounce items back to a grid, remove items, etc - those would all need to get updated
right now the only "truth" is a list of grid items that have their X and Y internally
that grid isn't so big right?
5x5 now, likely not (ever) bigger than 10x10
I don't think my solution is particularly awful in terms of memory/performance
it just... smells
then i'd just ignore any efficiency considerations and just avoid unnecessary allocations
where are the unnecessary allocs?
(creating the Dict when i make the call, versus keeping it around?)
yes
good point.. although moving it to a private member still incurs the memory cost
also, just a hunch... but it shouldnt be too difficult to maintain a open-positions list... it might be more effort to include in each game action... but thats basically how efficient data-structures get efficient... by maintaining some invariant on each add/remove/shift/rotate/....
not that that's a huge issue atm - the server may have several hundred/thousand games at once, but rather the GetOpenSpot method is going to be called probably every turn anyway
it's uhm... super difficult to manage that, I think, unfortunately
well, turns arent frames 😉
there are dozens of game actions, and the elements themselves are serialized/deserialized and two states managed at both ends
so i'd probably worry about other things... just make it somewhat nice, so i can sleep
i'm not saying it's impossible but.. potentially a big piece of work
haha
thank you for the feedback 🙂
if you read my now deleted comment, please ignore it, I tested it further and i was wrong 😩
Is it possible to write native plugins for use in the Editor with loose C++ or Objective-C files?
No, they need to be compiled in to a library. https://docs.unity3d.com/Manual/NativePlugins.html
(I am only like 98% sure though so take that as you will)
It's a bit ambiguous in the docs, there's no mention of the Editor, and it says:
You can deploy macOS plug-ins as bundles or, if you are using IL2CPP, loose C++ files
But it seems you're right.
What are "loose" c++ files? You can compile libraries into native DLLs and they work fine..
@timber saddle
Do you just mean .. random files that don't have a corresponding project?
Loose as in not compiled into a native binary.
It's how Unity's documentation calls C, C++, Objective-C or Objective-C++ files that are just thrown in there as if they were C# files.
Ah
I use that in Android and iOS. Now I wanted to make something for the Editor when running on a mac, but it seems I need to make an Xcode project and build a .bundle file.
Slight pain in the ass, but I guess it makes sense, as it's not using IL2CPP when running in the Editor.
I guess I'll just have to bite the bullet ¯_(ツ)_/¯
ha - sorry I couldn't be more helpful 🙂
(I hope I didn't leave you hanging - I typed out the above and then had to go drop kids off at taekwondo and forgot to finish my thought)
does anyone know why this bug occurs (when i add the conditional before adding the dict), and then subscribe a object to a group, and try to subscribe a new object to a group, the new object dosent subscribe, however when i dont add that conditional, the objects all subscribe fine, however i cannot resubscribe a given object to any group while that object has been removed from a group and before it is deleted. The outcome i want is one where when i add a object, and then remove it, and then add it again, it adds like normal, and it works for any object i allow it to, basically the oposite of what the bugs do
remove script
video showing the bug
you need to post the whole file somewhere, that's not enough code to know what's going on
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
i mean thats basically all you need but sure anyways
This is a really dodgy way of writing this sort of code for dictionaries of collections.
The usual way would be:
if (!dictionary.TryGetValue(key, out var list))
{
list = new List<T>();
dictionary.Add(key, list);
}
if (list.Contains(value))
{
return;
}
list.Add(value);
Something like that.
If you don't need to perform any more additions or processing in the addition stage you could simplify it to something like:
if (!dictionary.TryGetValue(key, out var list))
{
dictionary.Add(key, new List<T>() { value });
return;
}
if(list.Contains(value)) return;
list.Add(value);
Similar thing for removal, use TryGetValue - exit early if there is nothing found.
Call remove, if the collection is empty, remove the key from the dictionary.
Trying to do cylindrical UV mapping to an arbitrary, but closed, polyhedron mesh. I’ve got it ALMOST right, but I’m having trouble with the area where triangles cross the UV.x=0 and UV.x=1 boundary.
I THOUGHT I had an algorithm that fixed it, as you can see the before & after results in this image.
Unfortunately, this does NOT work for ALL meshes, - you can see the before & after results with this mesh- clearly it didn’t work so well. And I’m not sure why it is failing in some cases.
The code I’m using takes a mesh as input, and attempts to compute the UV’s based upon the vertex positions, with the assumption that it is closed, and centered around 0,0,0 in modelspace. It’s just a few functions, you can find them here. https://hatebin.com/qnmarqmynf
^ other UV problems remain near the poles, but that's just the nature of cylindrical mapping onto a sphere-like shape. I'll deal with those later, if at all.
oh. I never actually asked a question, lol. Can anyone find the flaw in the linked algorithm?
Don't be mad, but uh CylindricalUV calculates longitude incorrectly. It's opposite over adjacent. Your components are reversed
the solution for me to normalize was simply taking the animEvent.time / animClipInfo.clip.length
Has anyone ever encountered a bug in which runtime errors aren't displayed on the console even when you explicitly throw an exception at Start() function? Debug.LogError prints okay but not runtime errors. Kinda having a hard time testing/debugging things 😦
I HAVE had unity gobble up some exceptions I generated ! usually in GUI stuff.
It should have thrown an exception right away in the end of the console but it didn't
anyone knows how to look into this further? I can assure that this exception is not yet catched in anyway.
not caught by YOU.. but if you code is being called by unity itself.. that COULD be withing a TRY block
did you get any solutions for that?
I used Debug.Error instead 😦
It happens also with NullReference exceptions when I try to invoke methods from null objects
that's just sad. I hope others can shed a light on why this is happening.
@modest lintel it was you that pointed this out to me the other day, no? ^
does anyone know how to render an RT with defaultHDR format into a png? doing the conversion from HDR rendertexture to texture2d format gives me conversion errors like "Remapping between formats 74 -> 52 is not supported" depending on the format.
i want to encode as a png, if the RT / texture are in LDR, then it all works fine, but when i try to use HDR RT then it breaks down. i came onto this when experimenting with switching the project to linear.
PNG doesn't support HDR, which is likely going to be a problem.
Not an expert, but wouldn't you need to convert the HDR texture to the right depth first?
yeah, so thats what im trying to do but it wasnt working. trying to convert the hdr RT to a texture and then encode that texture as a png
but not sure of the correct process that allows conversion of an hdr RT into a texture2d. seems like none of the texture formats are compatible
Doesn’t RGBAhalf work? At least ARGBhalf is the default HDR render texture format, so aside from byte order you at least have a matching color structure.
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++) {
Debug.Log(int2DArray[x,y]);
}
}
O(n) or O(n^2) complexity?
settle a bet for me 😐
Big O notation is relative to your array size, so it would be O(n) which would be O(height * width) while O(n^2) would be O((height * width) * (height * width))
I think asking "O(n) or O(n^2)" is meaningless without talking about what "n" is supposed to be, because it does not appear in the code at all, and in this case it's imo not obvious enough to simply omit it.
Just say "O(height * width)" or "O(n) where n = height * width" and there's no need for any arguments.
Can you give me an example for this case that would result in O(n^2)
I mean it literally c an't be O(n^2) since n is one variable (unless width and hegiht are equal)😛
My point is only that "In O(n), the n refers to the array size" is a convention that is used because it's often convenient and obvious what is meant.
The fact that you asked this question here in the first place is, to me, sufficient evidence that it wasn't clear enough to someone what n is supposed to mean. The right answer is to just clarify, instead of semantic debate about how convenience conventions should be applied to this specific case.
(Other than that: If width and height are related, O(n^2) often becomes a reasonable answer; and that kind of context is obviously always missing from a short snippet like above)
O(n)
It's not really an algorithm though, it's just exactly n steps. (maybe this is debatable maybe, I just mean big O is not necessarily relevant here)
i thought it was more about the growth rate as n gets bigger, so if height is a function of width or visa versa it would be O(n^2) but if they're unrelated it would be just O(n).
edit- wait I am wrong unless you take width as n in the O(n^2) case, and array size as n in the O(n) case
Yeah, well O is worst case number of operations in terms of input size.
So a linear search is O(n) even if you're searching for the first element. That would be the best case which is a single comparison, but the algorithm is still O(n).
i.e.
var array = new [] { 0, 1, 2, 3, 4 };
Array.FindIndex(array, 0) // 1 step
Array.FindIndex(array, 4) // 5 (n) steps
But FindIndex is O(n)
Simply stepping through an array to the end is best-case, average-case and worst-case n operations.
So it's just not that useful a thing to discuss.
in this case the worst case is also the best case anyway right, since there are no early outs
Exactly.
So it's O(n) because a 2D array is just a single array with some syntactic sugar
Internally it's just a 1D array with a pretty accessor [a, b]
Your code is just a single linear read of that array (containing width x height elements)
The reasoning is relative to how often the elements are reoccurring. Since you're only iterating through each element once, your cost would be n where n is your number of elements. If you were to iterate each element twice, it would be O(2n). Thrice O(3n).
It is neither without definition what is being counted, what n is and what the return condition is. I.e. one could argue it is O(1) space if we ignore string allocations. anyone answering that question with a clear choice has no clue how complexity analysis works so nobody wins the bet
+1
Hello this is my current code to zero out the position how can i make it more smooth
transform.localPosition = Vector3.zero;
Think about it - you'll need to adjust the position a little bit at a time each frame until you reach zero, right?
you should use lerp or slerp
Yeah i tried this transform.localPosition = Vector3.Lerp(transform.localPosition, Vector3.zero, pickupSmoothTime * Time.deltaTime);
but it didn't work well
where are you running it?
ohh
Remember you need to do it a little bit each frame, so it needs to happen every frame
in a method
not just once
oh srry didnt see this i went to sleep last night
so does try get value not return null if the value dosent exist?
that way it dosent break the compilation process
TrytGetValue returns a bool - true or false - to let you know if the object was found for the given key
the actual value that was found (if it was found) is given to you as an out variable
ah
the way im doing it would need the list object to be created during the set is added to the dict
nvm
i realized i could literally just plug the list = new list<T> into the dict val
How can i stop the Flashlight rigidbody from sliding
Is it possible to call a method with multiple arguments in the UI system? (UnityEvents)
no
Alright, thanks for the answer
i have lots of arrays with 512 floats in them. I want to sum them all, into another array of 512 floats. What's the fastest way to do this?
But you can pass in a reference to a scriptable object that can contain many fields
Might try that
for loop with an accumulator
Yeah, no 'magic' way to do that. Just gotta loop over all of them.
I was gonna say make an int 'i' and then do foreach(int i in array) { sum += i; }
don't think it would be lol
Yeah my bad. But it would need to be float not int
right
(That is what through me off for a second there)
One-liner ```cs
float[] sums;
List<float[]> allMyArrays;
sums = allMyArrays.Select(it => it.Sum()).ToArray();
That would be less efficient wouldn't it because of the ToArray()?
It would require an additional loop through all of the items.
maybe not... since its lazily evaluated item by item... maybe the compiler is smart enough to figure out its a simple map-reduce.
Nah, I don't think so. The source code doesn't look like it would but I could be wrong.
Also I could be wrong but it sounds like they want to sum by index across all of the arrays (sum all floats at 0, then all at 1, etc.)
SceneManager.LoadSceneAsync(splitName[0], lsm??); Why does this give me an error?
Doesn't the '??' check if the value is null?
No, it is the same as doing myInstance != null ? myInstance: otherThing
Sure thing.
i wish i could understand that IL vomit that LINQ produces
Lol I don't either. I was talking about the C# reference. I just mean I would be surprised if the compiler could optimize it like that.
my gut feeling is that getting a pointer to each array, and then summing each via to the next via float4 casting will best SIMD it.
I have another suspicion that memcpy of each array onto the stack will make this even faster, as it will reduce memory accessing time.
how would that make memory access faster? or do you mean prewarming L1 with the array?
pre warming doesn't seem to work nearly as thoroughly as would be nice for this, and memcpy is so fast that two can be put into two stackallocs, and summed, very fast.
and the order seems to matter, too. So creating the target stackalloc first, and then creatiing and copying into the two to be summed, and then doinig the summing, is faster than doing it the other way around. Then copy back out, if necessary, or keep cycling through the remaining arrays to the two input stackallocs, with memcpy
probably fewer pipeline flushes that way
So is this the correct usage of the operator?
agent ??= GetComponent<NavMeshAgent>();
I read up on it
Yup
Cool, thanks
And does this check if target equals null?
target ?? null
To me it seems the same as ==
No it returns the thing on the left unless it is null then returns the thing on the right.
So in that case it is exactly the same as just doing target
Because you are returning null if target is null
oh thanks
So, if I wrote var c = a ?? b if a is null, it returns b, otherwise returns a?
correct in syntax, but something you should never do with anything that derives from UnityEngine.Object because of the way Unity overloads the equality operator
Good to know, thank you
And one last thing
if (TryGetComponent(out agent))
agent = GetComponent<NavMeshAgent>();
This checks to see if the object has the NavMeshAgent component, and if it does, assigns it, is that right?
The GetComponent is redundant.
Oh
If it has a component it will assign it to the out variable.
Cool
So I don't even need the if
TryGetComponent(out agent); This auto assigns 'agent' to the NavMeshAgent if the object has it?
Correct
Awesome, now I wonder why every tutorial I've seen does not do this
Thanks again
I guess this is safer than a regular GetComponent because it first tries to get it?
It's like try{} catch{} ?
No, it is like
agent = GetComponent<NavMeshAgent>();
return agent != null;
ah
It is more performant in editor too because it does allocate memory if it does not have the component.
Good to know
note that you should not use ?., ??, ??= on UnityEngine.Object types
after some testing in the rabbit hole 😳 ... turns out even a simple SIMD approach with 6 extra lines of code is 10+ times faster than a basic for loop. takes adding 169000000 floats in a parallel.for on 12 cores to reach that SIMD performance.
I am not familiar with this, are you able to share the code (even if not pretty) so I can take a look at what it does and how it works?
Reducing float[8192][8192] to float[8192] via 67100672 float additions ...
Basic 181.907200 ms
Parallel SIMD 25.687800 ms
SIMD 15.813900 ms (vector size = 8)
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Interesting, thank you. Would you be able to explain how the SIMD method works, or at least partly? If not that's fine too, I can google it to learn more too. 🙂
Those vector operations get executed with special instructions (single instruction multiple data = SIMD) on the CPU that can add/multiply/divide/... up to 8 single precision floats or integers at once... So you copy the values of a array slice into the vector, then add it to result vector, all in one operation, then shift the slice start index by vector size, and repeat... at the end you collapse the result vector, add the few array entries that didn't evenly fit into a vector and done. @urban warren
static void TestSIMD(int n, float[][] rows)
{
Stopwatch sw = Stopwatch.StartNew();
float[] result = new float[n];
int vectorSize = Vector<float>.Count;
for (int i = 0; i < n; i++)
{
Vector<float> accumulator = Vector<float>.Zero;
float[] row = rows[i];
int j;
// SIMD add
for (j = 0; j < row.Length - vectorSize; j += vectorSize)
accumulator = Vector.Add(accumulator, new Vector<float>(row, j));
result[i] = Vector.Dot(accumulator, Vector<float>.One); // reduce the vector
for (; j < row.Length; j++) // add the odd tail to the result in case n % row.Lenth != 0
result[i] += row[i];
}
double lap = sw.Elapsed.TotalMilliseconds;
Console.WriteLine($"SIMD {lap:0.000000} ms (vector size = {vectorSize})");
}
so very very glad you're seeing the same huge gains. I thought I was doing something wrong.
or imagining things.
i always thought that those were at best 2X to 4X faster (in practice) ... but this is very nice. with not much extra effort
In one endeavour, I got SIMD + stackallocs to be 12x faster than my best efforts with Burst+ Jobs...and thought I was losing my mind.
but isnt burst supposed to use SIMD?
I see, sort of. I will need to write it out my self and mess with it to really understand I think, but you definitely made it a lot clearer for me!
The Vector thing was what was confusing me the most, which you cleared up.
I never knew what SIMD stood for, thanks.
I feel like with such an increase in performance people are really sleeping on this...
Indeed, but Burst still has to do all that work of getting things sorted out its way, etc etc... whereas with stackalloc and memcpy and lining stuff up, I could easily beat its way of lining things up to get ripped through by the registers
And my initial tests with float4x4 have turned in StUNNING results.
true... but my pitiful attempts at using memcopy/stackallock made the SIMD method 3X slower 😉 so i guess it has a lot of potential but its very non-trivial to achieve
it's swings and roundabouts. Sometimes it's needed, sometimes it's just extra overhead.
For me, it's been far easier than ANYTHING i've done with unity in the 2.5 years I've been using it, because it reminds me of my C childhood.
tbh, i'd rather write that memory stuff in plain C somehow... but with Span<> and such, i guess one can get rather close in convenient/safe c#
I can kind of intuit where and how and what to do to get the SIMD and vectorisations to fly, and it's been super relieving to think outside of FARKING OOP!!!
AGREED! But it feels like having an illicit affair, doing low level in C#. Fun, fun fun!
OOP is just so slow. And ECS has so many bloody rules.
By OOP being slow... I mean me. It takes me forever to work out an OOP architecture, for anything. This stuff, I can do everything I want, and have cycles to spare. Literally.
my issue with ECS in unity is, that they have to try to make something that works well when fully optimized for a particular application (a specific game/team/pipeline say) and make it generic... so it will end up very low-level and provide little improvement over DIY, or it will have, as you say, so many rules and edge cases that it is out of reach of the normal people that are supposed to benefit from it
most of these benefits you can get by 'tricking' the pointer into thinking it's looking at a much bigger type, because they're all 1D arrays. So you can rip through floats as though it's a float4, or even a float4x4
I need a billion thumbs up for this comment. You NAILED IT!!!
this is my new favourite aspirational video in regard to performance sainthood https://www.youtube.com/watch?v=Ur53sJdS8rQ
In this 2021 GDC talk, lead engine programmer Adrian Bentley examines the technology choices that made Ghosts of Tsushima’s fast load times and compact patch sizes possible.
Join the GDC mailing list: http://www.gdconf.com/subscribe
Follow GDC on Twitter: https://twitter.com/Official_GDC
GDC talks cover a range of developmental topics inclu...
THANK YOU!!! Will queue up to watch as I nod off a little later tonight
I'm not able to use Deconstruction syntax with Dictionaries:
Assets\BottleShooter\Shop\Shop.cs(16,56): error CS1061: 'KeyValuePair<string, ShopDataAsset.GunData>' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'KeyValuePair<string, ShopDataAsset.GunData>' could be found (are you missing a using directive or an assembly reference?)
Assets\BottleShooter\Shop\Shop.cs(16,46): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'KeyValuePair<string, ShopDataAsset.GunData>', with 2 out parameters and a void return type.
So far from https://stackoverflow.com/questions/42549491/deconstruction-in-foreach-over-dictionary# I saw that I might need System.ValueTuple which needs to be imported by NuGet, but it's already available in the code.
I'm using VS Code 1.61.1 and C# Extension 1.23.16 which is supposed to support .NET Core.
Default Unity settings use .NET Standard 2.0. The last comment on your stackoverflow link seems to suggest it will be included in .NET Standard 2.1, which presumably means it is not in .NET Standard 2.0. This page confirms that hypothesis: https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.keyvaluepair-2.deconstruct?view=netcore-2.0
Indeed, and otherwise Unity uses .NET Framework 4.7.2.
Or 4.x
Has anyone here used discord Rich presence, whenever it changes scene it break and gets stuck on whatever the last thing was.
Don't cross post
Is there merit in changing my node editor from XNode over to GraphView now that it has slightly matured or is GraphView still heavily subject to change and/or removal
GraphView will be replaced with Graph Tools Foundation
Which is still a bit too early to use, so....
I thought development on GTF had stopped and was replaced by GraphView actually 🤔
Since it is being used by ShaderGraph and the VFX Graph
or is GTF meant to unify the graph API including Bolt?
I don't know much about GTF apart from what I've read about in the NodeGraphProcessor issues, but it sounds like ShaderGraph will migrate to it in the future. (alelievr is a Unity employee)
https://github.com/alelievr/NodeGraphProcessor/issues/188
That does make it sound like that. I should probably wait for more details before making the switch.
Tho I see migration I wanna assume it will just shift the namespace, but thats a risky guess
Unity never rly gives a timestamp anymore, or so i've noticed
The hardest part of the migration will be to migrate existing graphs but I dont think that ll be that big of a deal since my node system is a chain of scriptable objects 🤔
Hey friends, we've built out our game for Mac and are encountering some issues. The game runs fine in the main menu and even through some gameplay, but after introducing some effects to the scene (by way of firing weapons) the Mac client crashes.
It gives out a bug report log, but I'm unable to discern anything useful from it. Something I've read online is that pushing the GPU on a Mac too hard will cause this type of crash, but from reviewing the Profiler on PC I can't imagine it's something like that.
To me it feels like a certain element of some of the FX causes this issue, but so far through process of elimination we've been unable to find more clues. We're going to keep doing that, but I wanted to solicit any insight here in case this was a common issue. Cheers
No one can guess that, you'll to post logs or errors
I thin kyou should be able to symbolicate the crash with the symbols from unity
And what about the normal player log?
normal player log, like the console?
Yeah
unable to get a read from that prior to the crash, there's no prior warning
I will definintely check that again though
what do you mean by symbolicate the crash?
4 UnityPlayer.dylib 0x0000000101897c67 0x101235000 + 6696039
These bits point to certain methods, if you have the symbols (dsym for osx iirc) you can match them up and fill them in automatically
hmmm
Unable to read as in you can't read the log or there's nothing in the log?
You can output the log to a file
nothing in the log that I saw, I'll do the text output but IIRC there was nothing logged aside from networking logs
could've been there for like a frame and I missed it, will defintiely double check when I can
being able to translate those codes to methods to get a better sense of the specific issue would be really helpful
I only know how to do it with xcode for mobile projects, which is really annoying to do
Since it relies on xcode finding your dsym, which it fails to do most of the time or just won't do until a few days later
very interesting, wasn't aware of that process. googling into it now, thanks for the guidance @flint sage
How did you go with this research? Looked at Audio?
been tricky trying to get the symbols read correctly, not sure I know what I'm doing
there is indeed audio clips on some of the fx, do you think that could be it?
Yes, there's a good chance, if you're doing syncing of effects with audio, that that's part of the problem with Unity and a Mac. There's been a long and weird history of them not playing well together. Best to "pre-warm" all audio sources, and pool.
Righteous! We are currently pooling the SFX but have them paired (meaning on the same gObject) with many VFX. Appreciate the angle mate cheers
Be very careful moving them around fast (audio sources), it's best to completely disable them, move them, and then add whatever audioclip you need to them, then activate and play. And never use PlayOneShot, as it's a monster.
You can swap audioClips as often as you like, as fast as you like, as this is light and very fast. So you only need just enough AudioSources for the maximum number of sounds you'd ever play.
And there's a hard cap, by default, at 32 Audio Sources, too... I think. set this to 128 or something like that, just so you never hit it.
and the above line is in red, so I'm not sure if it got sent.
I haven't seen that before, haven't used discord a huge amount. The line is about setting audioSource limit to higher than the default 32 (for Mac), to something like 128
Also be very careful with reverb zones, make sure you have only ever got one impacting any audio source, as this gets weird, real fast.
hmmm, it very well might be an instance of too many audio sources, that seems very possible
so the scenario you're outlining would involve 2 object pools, one for VFX, and one for SFX
and rather than each SFX object being it's own per sound, you recommend using one pool of X amount of audio sources, and swapping the clips out by use?
Yes, exactly, try to use the fewest pooled AudioSources you can, as there's some efficiencies that come from this, and you'll get lots of other strictness in what you program that prevents other audio issues. Mac and Audio are bad, Mac and Unity Audio are very bad together.
Much of what I'm saying does not apply equally to iOS. It's much more of a Mac problem than anything else. This is partly because of the age and lack of updates to the FMOD version in Unity, Unity's ways of handling audio, Unity itself and the nature of security in modern Mac chips with regards Audio
The easiest way to solve this is to pool audioSources, in a manager, and have your VFX request audio sources sufficient to perform the entire FX for any given event. I know it's a pain to do this, but the gains are efficiency and stability. and you can be absolutely sure you're pulling deactivated audioSources, positioning them, adding the desired AudioClip and setting all values needed and THEN and ONLY then enabling the AudioSource, so it doesn't teleport through a bunch of reverb zones and other potential issues with rapid moving of them.
so right now we have a single VFX pool, with a bunch of different VFX that mostly all have Audio Clips on them
what we do is disable the gameobject, pool it, and turn it on when both the VFX and SFX are needed
I'm confused as to whether you think they should be separate GameObjects, or if the Audio Clip just needs to be specifically disabled
I know... I went through all this. It was a pain. It was a lot of work, but the result, for me, solved all problems of audio and Mac/iOS, and gave me better performance, as I used a lot less Audio Sources as a result.
so is the true goal to lower the amount of Audio Sources?
and by lower the amount, you mean lower the amount in the scene, not lower how many are active?
That's only one of the goals. It's more of a side effect, that you have lower numbers of them, and this is greatly beneficial.
Hi, is there any way to avoid having a state in the Animator not get stuck and not exiting the current state when the transition condition has been met already ?
alrighty, I think we can manage that. It's really just a matter of splitting up the prefabs, splitting the pools, and drastically limiting the pool number of the audio sources
@sturdy tartan not exactly sure what you mean, can you elaborate?
sure
also someone's going to suggest posting in #🏃┃animation instead so I'll do it first lol
Yes, the drop in audio sources, although a side effect of this approach, will be a huge performance booster, and remove other issues. But the real goal is to get you absolutely sure that you have a stable movement of deeactivated audio sources to positions, and certain control over their state.
it also seems like having audiosources moving around is not optimal? we are doing that in one or two cases to create a doppler effect
here's an illustration first to explain
Use ScriptableObjects to store the state of the AudioSources and their clips, so that you can do this efficiently, or public structs on each VFX unit with all the details needed to set to the audioSources as it pulls them in.
the animator get stuck at the animation in blue while the transition condition has been met
it can get out of it if i hold the transition condition true for 3 s
A few situations where you move at game object moving speeds (audioSources on moving game objects like rigidbodies) is fine. It's the teleporting to a location to play a sound that's the real problem.
but doing so, ruin my combo
and just to make sure I understand, teleporting to a location is fine as long as the AudioSource is 100% disabled?
because I do plan to place the sounds based on location
As victory said this is not the right channel since this little to nothing to do with scripting. #🏃┃animation is the one you want.
And I fully understand what you're doing, the doppler effect, in conjunction with the reverb, is surprisingly VERY good in Unity.
i'm sry, i'll go there ^^
yeah right? we threw it on to just see how it worked and it was pretty nice out of the box
no worries @sturdy tartan they will likely be more helpful, I can't tell what your issue is
Yes, fully disabled, and even preferably without any audioclip during its movement to be doubly sure. Just program super, super defensively with regards AudioSources. There are myriad issues with them. There's not just one or two cures, this is a VERY old system that's never had much in the way of bug fixes.
well the thing is that the character get stuck at a state in the animator as in the picture while it should transition to the next state since the transitioning condition in the image has been met
If you crank up the doppler effect, to absurd numbers, it's still good!! Especially with short sounds with a bit of punchy resonance at the start that are in the same reverb zone. Can be quite entertaining.
Also, the Echo Audio Filter, at very low numbers of delay (think 11 through to about 24) with decay set to 0.9 or above, is super interesting, too.
The echo filter has a bug in the delay, you can't animate it. Unity knows about it, but I don't know when they'll fix it. So if you want to animate it, you'll have to do it with code.
As we saw with my inability to help with that animator question I'm pretty clueless with the animator so code's fine by me lol
I think this whole rework will help us take a closer look at things like audio effects, we're not using many rn
AnimationLegacy is worth a billion times more than Animator! If you can, don't use Animator, for anything!
And since you're pooling effects and stuff, DO NOT USE ANIMATOR!!!
There's huge problems with pooling and restarting Animators, that have never been fixed, that will drive you insane.
I'm using Animator
I'm gonna keep using it, our implementation has no issues so far
I'm not using it for effects though, just the main player character
Once you get to an issue, consider switching. It'll be quicker than trying to correct the ways ANimator works.
Oh, that's different. if you need timelines for effects, use Legacy Animation.
Is the legacy animation even still in? I thought they removed it by now?
It wont be removed until well after they've made a similarly performant replacement, which isn't on the horizon.
AnimationLegacy is VERY lightweight and very fast. And using Evaluate on it is often quicker than making custom ease maths.
I don't see it in any menus....
just add a component to any object: Animation is the name of it.
Oh, it is Animation I thought it was previously called something like Animation - Legacy
othe rthan the docs, they dono't call it Legacy, because it's not really a legacy system, it's the old system, that's lighter and faster.
Unity's naming conventions are bizarre. The sequencer is called Timeline, the timelines in both Animator and Animation are called timeline.
are you referring to the pooling classes in Unity or roll-your-own?
what is pooling classes in Unity?
Whatever it is I am talking about rolling my own script
2021.1 (IIRC) added them: https://docs.unity3d.com/2021.2/Documentation/ScriptReference/Pool.ObjectPool_1.html there are several variants. I use them in my editor extension and they work fine. Performance - unsure.
not this, rolling my own
which one should i use for better performance stack, queue or linked list
Depends on what exactly you want to do… all of them are potentially linked lists
i want to store particle systems that i will reuse as effects
I mean algorithmically, and quantitatively
30 objects in a minute
just use a list
i find queue easier. Is it favourable than list
it really makes no difference
a list is also a stack, backed by an array
and for pooling, a queue adds no benefit
understood
Queue has methods ready for you that do all the job for inserting or taking an item from it
But that's pretty much it
let's say i have a character when it moves there are some effects that happens like dust effects on the ground. for things like that i don't need a object pooling right
A simple particle system can do that
yep
With enough modules enabled, mainly "rate over speed", you can mimic disabling it, as it will not be emitting if you don't move
got it
if i use queue, since it is FIFO(first in first out) then after dequeuing an object won't the program has to reshift all of it's other object indexes
Not if it is implemented as a linked list
i see
Yeah if it is, it just has to redefine where the "head" is, without shifting
Overall, linked lists are terrible for performance though
much more efficient to implement the queue as a list/array with two pointers and resizing it occasionally instead of spreading individual nodes all over the heap
Lists aren't great for performance either. If you're going to make a pool of objects then use an array and set up enough space so you never need to resize
List can do that too, has the same performance as a plain array and has automatic resize built in, just in case. While there are microscopic differences in performance between the two, they aren’t even 10%, whereas list vs linked list can be an order of magnitude faster
Most information I come across claim that the array is always the fastest option for read and write operations
if you're concerned about performance differences between arrays and lists you're likely better off making your own engine. simply by using Unity you're accepting so much overhead that those minor discrepancies aren't really relevant
IMO
Just an opinion but I think when there's no need to resize then array would be the best option
it’s even better to use stackalloc on the array and do math only with simd, but you’ll spend 10 times the time writing the code… and first of all that has to be worth it IMO
Right but in this particular case using an array over a list isn't that much work, but one should do what makes the most sense to them of course
I would disagree with this rather heavily.
There are plenty of times when you are making systems that built on top of Unity that either operate on a large number of items or are called very frequently and are relatively expensive where you would want to spend the time to optimize them where you can.
An example could be an AI system. Should you just built your own engine just because you want your AI you have good performance?
Of course I'm not saying you should always spend the time to optimize things, to the level of array vs list, it of course has to be worth it for the time.
and array vs list is also just a stopgap towards real optimized systems… hello SIMD, hello Parallelism, hello GPU compute, hello ML, hello pinned memory, hello structs of arrays, hello caching, hello branchless programming, hello better algorithms, hello better architecture …. Endless possibilities for PhDs 🕺
looking for some help regarding pathfinding
im using astar pathfinding and im having trouble with gameobjects running into eachother and getting stuck
is there a way I can have the paths of 2 gameobjects not intersect with eachother?
Are you using your own implementation?
using the astar pathfinding project
In that case it comes with local avoidance components. You can look on its doc site for more info.
I think its reserved for pro users only
Ah, yeah.
Hey y'all
I've recently turned to a one-texture-atlas-for-everything solution for my level meshes since it reduces the drawcalls from 2000 to like 20
But as a result of this I have no easy way to differentiate surface types by material anymore.
Are there any tricks that don't involve having seperate colliders per material surface?
This is for things like footsteps or impacts
Also, now that I'm reading - what is the advantage of these built-in pooling classes vs. writing a manager that instantiates and manages objects yourself?
https://github.com/Unity-Technologies/UnityCsReference/blob/master/External/MirroredPackageSources/com.unity.ui/Core/ObjectPool.cs
This one doesn't instantiate, it only manages regular C# classes
oh, sorry. wrong one!
It seems 2021 source is not live yet
They stopped adding new sources a while back and it's just another "Why the hell, Unity?" moment
It is handy they provide a ListPool, DictionaryPool, and similar more generic versions
oh that's super disappointing.
They stopped ages ago
I know I was just poking around
It doesn't make it any less disappointing
More disappointing actually
Yeah, it blows hard
Could at least say that Unity's C# source was available, now you can't even say that
I was hoping the C++ would be made public
Yeah, exactly.
UE is fully OSS right?
Wow it is. That's so cool
They even have a guide for building it.
I guess if you have licensing it doesn't really matter if you're open source.
Maybe Unity just do it for the paywall?
I'm not sure if I would use OSS, but it's certainly source avaliable
Yeah, not free but open and you're allowed to modify it.
I have no idea why Unity does what they do. There's so many amazing things they could provide that'd add so much quality
stuff that the Needle guys provide without even having proper access
UGUI had a live repo.
It was just a mirror too though, they weren't actually working on it.
It would be awesome if we could actually open PRs against their modules. I thought when they started using UPM that everything was going to broken out to GitHub
These are things I used actively, and still use albeit with a lot more caution
You can make PRs against stuff like the Graphics repo
Some packages are leading the charge on that sort of thing, but others are just becoming shut away again
Oh, nice. Is that a DOTS repo?
SRPs
The good thing about needle is that you can fork at least, and it still adds a nice way to merge it upstream changes.
Ah that is great.
And they're working straight into this?
1,654 branches!
Holy jesus time to prune
I have made one amazing PR https://github.com/Unity-Technologies/Graphics/pull/5347/files/398b6176870ec4776cb4651b5ef65fb612eb42ab
Wow you programmed Unity3d
Who knows, I may be in the credits now
"optimisations¹ for vfx graph"
how can i project a scene onto an object
hey. can someone please help me out on the two last arguments for the Crossfade animation ?
I wrote their help text in front of them
help with what?
seeing them like this , I can't relate the last two arguments...
as to what they mean
the NormalizedTimeOfsset is the start of the second animation ? ( also start of the fade )
( also sorry for the light mode there. i hope its not night over there )
I seem to have found a rather anoying compiler difference between VS and Unity. VS thinks this is fine, while Unity doesn't. It complains about casing lambda to lambda. If I remove the ternary so it's a direct setting, it compiles just fine. I'm guessing this is just straight up a bug and I should report it?
Comparison<Vector2Int> comparison = shiftAmount < 0 ?
(hexA, hexB) => hexA.x.CompareTo(hexB.x) :
(hexA, hexB) => hexB.x.CompareTo(hexA.x);
Unity doesn't have a custom compiler. it's just an old version of C#
it doesn't even have the keyword not , for exampel
so if(A is not B) is accepted in newer dotnet , but not in old version that Unity uses
Likely a unsupported feature in the runtime or compiler
Unity has a custom version of Roslyn and a custom mono version, it's not just old.
Maybe. It's weird that the lambda causes a casting problem though.
if u want the newer fancy C# features, u can use .Net 4.x from player settings
This makes it work 
I don't know what's the side effects though... so use it at your own risk
I think it's technically a bug that it's not casting the correct thing
yeah you could always find alternative ways 👍
Definately. Just felt like something maybe worth reporting if I've not done something wrong.
Nah, you haven't done anything wrong. There's no point in reporting it, Unity has to update the compiler/clr to fix it (which they're likely already working on)
they contain specific syntax changes though ?
@final kindlehey mate. I googled a bit and looks like I was wrong. then sorry. .Net standard 2.0 isn't necessarily older than .Net framework 4.x
the numbers are a bit misleading there
from what I figured, this column is what .Net standard 2.0 means
Ah. Thanks.
netstandard is a compatibility specification that contains all things that work in .net Framework AND .net core
yes. and now this question still remains. why some syntaxes are not supported ? if it's not really old
there is standard 2.1 for newer stuff
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#logical-patterns in this link for example, none of the logical literals are supported ( or and not ) . and it says they're from C# 9.0
standard 2.0 is probably C# 7.x
its the most compatible standard that still has sufficiently modern features... 2.1 causes all kinds of incompatibility issues with stuff that is stuck on framework472
could be useful
got it. thanks!
i'd suspect with 6.0 things will get better... up to now many considered .net core and 5.0 "unfinished" and didnt port their stuff over
things you could do with C# 8.0 ...
public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),
Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),
Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};
net core 2.1 is in one of the beta's or alpha's i think
once a stable version of that releases i'm gonna switch over because default methods for interfaces would be nice
2021 , yeah
yeah definitely . c# syntax as well as visual scripting ... im so waiting for 2021 LTS
Hey everyone! Do you know how to draw the basic inspector for custom PropertyDrawer ? I just want to be able to hide or show a variable when I use an enum
PropertyField
there's #↕️┃editor-extensions
are there any pros for making multiple prefabs for basically the same gameobject with different variations, instead of making 1 base prefab that you can load data into at runtime?
I have right now a creature base gameobject, and all variations of that gameobject should be more or less the same in functionality. they would differ in models, collider size, and a script that defines that creature and loads data(+maybe other things I can't foresee).
right now I feel like making a lot of prefabs is "easier" since you don't have to write extra code to load in data, and some stuff might be annoying to handle.
but I feel like 1 base prefab will be more efficient overall and scale better.
does anybody have some insight on this?
thanks!
i think this could be a candidate for scriptable objects
it would mean having a serialized field for the SO, then on Awake taking the values from the SO and turning that into the object
having many prefabs might not be scalable if there are many types and the variations aren't that large
yeah, thats exactly what i thought
Does anybody know if async unity messages are now supported? I mean Awake and so on. Unity's Cloud Code example mentions internal async Task Awake() inside MonoBehaviour which seems very suspicious.
They are
iirc they can also return void and do not have to be Task
Does this mean that C# multithreading is a reliable thing now? Or do they use custom scheduling sort of thing. And which Unity version does support this code?
mind though that async await without Task.Run stays on the main thread like a coroutine would
Yes, custom
it has some issues due to a thread.sleep(1) each time await/yield is called
that is great, I mean this is usually not guaranteed with classic async/await
I’d like it to be easier to have background threads out of the box
but async await wouldn’t help much with that anyway
I have a State machine running in code. When does it make sense to use mecanim?
Like, say I have multiple possible parry States(like sekiro) with the only difference being the parry animation and what attack state it could enter from. Is mecanim better in my case?
From my experience it is better to design your system with playables and custom state machine.
We did a system with Animation Controllers at first but it quickly became very unmaintainable and full of bugs.
If you still want to keep using Animation Controllers, try making all of your transitions from Any State, not building complex graphs.
Sorry for the delay in replying. Others have chimed in but here's my comment: What Unity is providing in Pooling classes isn't a replacement for a comprehensive pooling solution like (for example) Pool Boss (which I use myself for other things). What I found Unity's pool classes good for is when you have a subsystem that needs to create and destroy hashsets, lists, class instances and the like which are created on-the-fly. For example, my tilemap extension has a runtime library that would create a stream of stuff for the GC to handle. Unity's pool classes make it easy to set up myriad small pools to handle each of these - and you can customize the behavior of each pool for reinitializing the old class instance when you get a recycled one from the pool and also you can customize what happens when you return an instance of something to the pool - for example: nulling out old references to GOs etc. So they're useful for many things - you could build a general-purpose pooler for prefabs etc if you like but there's plenty of nice commercial pooling solutions for that already.
Hm
Interesting, it seems like such a basic task that it's odd to include it at all, I was wondering if maybe it made use of some secret native code optimizations or something fancy like that
hey yall, I posted this in general earlier but it got buried- I'm trying to find the gradient and/or contour vectors of a noise-based mesh for use with vector and/or tensor fields, and I haven't found any information online about how to do this- I understand that the tangent function does a little bit of what I want, but I don't know how to constrain it to the right direction or if there's a better way to do this
I have a piece of code to update some UI members of a game object, and I want to centralize it and be able to call it from a variety of places.. I wrote the code but forgot nullable types aren't supported (yet) in Unity. Any suggestions for the following? I'd like to not make one method for each UI element that needs updating, but also be able to only update a part of the UI element:
public void SetBattleUIStateImmediate(string? statusText = null, Color? battleStateColor = null, Color? iconColor = null, float? percent = null, string? hpText = null)
{
if (statusText != null) BattleStateText.text = statusText;
if (battleStateColor != null) BattleStateText.color = (Color)battleStateColor;
if (iconColor != null) Icon.color = (Color)iconColor;
if (percent != null) BattleHealthBar.Percent = (float)percent;
if (hpText != null) BattleHealthText.text = hpText;
}
Nullable are supported by unity though.
They are? I thought that was a c#9 feature
I mean, I could just wrap this in a nullable region but i thought that wasn't supported..
Nullable value types seem to be around since C#2
https://stackoverflow.com/questions/64229527/customizing-csproj-in-unity-enable-nullable-reference-types hm.. appears so, I'll try this out
I suppose what I remembered (incorrectly) is that unity doesn't support the null coalescing operator, but nullable types are fine
You might need to change null checks to .HasValue though.
Hmmm... A null check should work probably.
Hm.. MS VS doesn't seem to pick up the directory buildprops file
not sure I want to sprinkle that annotation everywhere i use it
also.. treat warnings as errors gang signs
You're trying to do nullable reference types. That's not supported in current unity version.
aye that's what i wanted.. nullable ref types
actually.. what's the difference in
string? nullable;
string nullable;
aren't those both the same thing?
oh well i suppose this works for me
public void SetBattleUIStateImmediate(string statusText = null, Color? battleStateColor = null, Color? iconColor = null, float? percent = null, string hpText = null)
{
if (statusText != null) BattleStateText.text = statusText;
if (battleStateColor != null) BattleStateText.color = (Color)battleStateColor;
if (iconColor != null) Icon.color = (Color)iconColor;
if (percent != null) BattleHealthBar.Percent = (float)percent;
if (hpText != null) BattleHealthText.text = hpText;
}
A string is a reference type, not value type. I'm not completely sure what's the deal with nullable reference types, since reference types can be null as it is.
They help the compiler with static analysis to better determine if a value can-be, is or maybe null so you get fewer null reference exceptions at runtime
I have an item that's de/serialized on the server/client that has a "GridItem" - an item that has some values like X, Y, hit points, etc. When I send the message to the client, it contains a serialized grid item that the client synthesizes (into a new GridItem) using a Clone() method on the serialized copy of the grid item (so that I can GC/discard the rest of the serialized message).
A) Is it leaky to not clone it and just use the entire message's instance of the GridItem (I realize it's going to keep the message around until the GridItem itself is discarded, but that's not leaky, per se, just not really efficient)?
B) If A, is there a way I can enforce cloning of the enclosed GridItem so that I know I've made a mistake forgotten to new() up a local GridItem as I am supposed to? Code below for reference.
[MessagePackObject]
public class BattleActionCreateFieldItem : BattleAction
{
[Key(0)] public GridItem newFieldItemClone;
[Key(1)] public Guid whichPlayer;
... other stuff unrelated to the GridItem ...
}
... on the server ...
BattleActionCreateFieldItem bacfi = new();
GridItem newFieldItem = new()
{
Contents = (GridSquareContents)crewUsing.ActiveAbilityValue,
Owner = actingPlayerGuid,
MaxHP = GameLogic.GetStartingHP((GridSquareContents)crewUsing.ActiveAbilityValue),
CurrentHP = GameLogic.GetStartingHP((GridSquareContents)crewUsing.ActiveAbilityValue),
IsSummoningSick = true,
};
bacfi.newFieldItemClone = newFieldItem;
... serializes the "bacfi" and sends to client ...
... on the client, deserialize and process the "bacfi" ...
private void ProcessAddNewFieldItem(BattleActionCreateFieldItem bacfi)
{
GridItem newGridItem = GridItem.Clone(bacfi.newFieldItemClone); // This or just reference directly?
Battle.Fields[bacfi.whichPlayer].Add(newGridItem);
OnCreateFieldItem?.Invoke(newGridItem);
}
I don't remember but doesn't messagepack support deserializing into an existing instance?
We're not cloning the object but we're also not doing something uber performance @misty glade
Hey, so have a bit of a weird problem, I have a camera separate from the main one rendering a weapon, that goes to a render texture to display on my GUI. But as part of the GUI, I want lines to point to certain areas of different weapons. I have all the positions for the points and references and everything, my problem is figuring out how to get the exact point on the screen from one of my transforms, because the actual item and camera are far off screen below the map, and only appear on the screen from a render texture, so something simple like just using WorldToScreenPoint produces inaccurate results. Any ideas what to do about this?
if your two cameras render to similar size destinations (i.e. the render texture and the screen have the same dimensions), just use the gun camera's transform for the w2s transformation
Use WorldToScreenPoint on the gun camera to translate the point on the gun to a point on the render texture. And then use the local transform of the render quad (or plane) to find the world point that it is being projected onto, and use WorldToScreenPoint on the main camera to find the exact pixel that corresponds to.
I tried that initially, thought that it might work, but it rendered in the wrong spot, tho it was close. Tried as an experiment fixing it with transform positions of the rendered image etc. But not only did I have a problem when the screen resolution changed, I also had issues with the points being close, but not quite lining up with the actual positions.
Hmmm so obtain the screenpoint from the gun camera to translate it, would it be worldtoviewport because the camera actually isn't rendering anything to the screen? or does screenpoint still work? Cause I tried viewport then multiplying by the width/height of the image renderer because my screenpoint seemed like it was giving odd results.
That would be easier I guess. Viewport space is (0, 0) to (1,1). Screen space uses pixels.
Ack, having trouble wrapping my head around how to convert a screen space to the right point using the transform of the render texture, to the convert again to screen space using the main camera, I guess time for a break to come at it later.
is the render texture displaying on a quad?
it is displaying on a GUI image
this?
hm
i think transform.TransformPoint will still work
but the result might need to be shifted
one thing you could do is compute this point, and then place a tiny cube there to see if it corresponds to the correct spot
hmm I'll check that rn, I have a gizmo for displaying the point
er, tiny square on the canvas
since it is on a canvas, you want to stay in canvas space
since I assume you'll be drawing the lines, etc on the canvas?
Don't know if I'm using it right, I'm getting odd wild results. I also have the line position thing done so that points to the final position. Cause of issues for now I have it set to scale a few rect images to get the right position, and as far as I can tell, that part is working perfectly.
start by placing something (like a small rectangle) on the canvas at the same location as the render. And then once that works, add the offset you get from WorldToViewportPoint, scaled by a certain amount. If nothing happens (the rectangle stays in the center of the render), you might need to increase the scale.
I just did a double check, it seems that grabbing the render images transform.position gives me an accurate starter position.
Hmm actually managed to get a semi consistent result as a quick experiment, I'm concerned I brute forced it a bit, and had to scale by over 1700, and then recorrect with a vector3 after
screenPos = imageRef.transform.position + camRefPos * scaleRef - camRefPositionCorrect;```
hmmm, maybe the extreme scaling came from converting to screen resolution? rather than the rects transform scale
yea there's some conversion between the camera resolution, canvas resolution, scale. I'm running on no sleep, can't think about it too precisely
hmm so I need like a canvas point to screenpoint conversion essentially
var worldPoint = canvas.transform.TransformPoint(localCanvasPosition);
var screenPoint = camera.WorldToScreenPoint(worldPoint);
there are also some methods here for doing the reverse
https://docs.unity3d.com/ScriptReference/RectTransformUtility.html
Hello guys. Instantiating object will also create new Instance of the material and I don't want that. How my objects can have same instance of the material on Instantiating?
Afaik, you can't really do anything about it. Every renderer in the scene gets an instance of the material created for it.
Hmm, that is less optimized compared to the example where they have same Instance of the material?
Hmm... Maybe I'm wrong.
Are you accessing the instantiated object material via renderer.material?
Yep, I need to change color
That's why it creates an instance
You can do renderer.sharedMaterial to change color to avoid creating an instance of the material. But then all of the objects with that material would get affected.
sharedMaterial still creates instances
And this is what I actually care the most
Since I have like 200 objects in the scene with different instances
Donno. Maybe you're accessing .material somewhere else..?
Yea, because I have to access them. I will try to make multiple Instances and instead of changing color I will try to assign new Instance of the material. Hope that this can work
Thanks for the help!
But yea, he still creates instance even when its not assigned
I have a list of files I download from a server and instantiate them in the scene as GameObjects. All of them are disabled at start. Next I want to activate and deactivate one by one in a continuous order. with every time only one gameobject being active in the scene. The thing is the ammount of gameobjects is huge as seen in the profiler tab. This causes problems such as crashes when running on mobile. What are my options for object handling so the memory usage is lower/better managed ? Have in mind that every mesh is different from the other.
Hi there
does anyone know if accessing a singleton instance of a script is better by variable or by getter function?
Like if I had this
public static EnemyController instance;
private void Awake(){
if (!instance) instance = this;
}
is it better to access it at runtime with a variable or with a getter function?
A property is better purely because you then cannot set the instance from outside the class
how come I can't?
if you dont have a setter, only a getter you cant set the variable by design
what I meant was for that bit of code which is better?
this?
private EnemyController EnemyController => EnemyController.instance;
or this?
private EnemyController _enemyController;
void Start(){
_enemyController = EnemyController.instance;
}
for access in other scripts
you cant access private stuff in other classes tho
not sure if something is going on in the back regarding memory management or something when accessing this dozen of times at runtime
so neither will work
@onyx blade this is in a different script, not in EnemyController
the precise question would be, does it make a difference performance wise if I do/dont store the instance of a singleton in another scripts variable?
and instead access the instance with a getter
It probably costs a tiny bit, unless the compiler inlines the calls. Even if it doesn't you probably not gonna notice any difference.🤔
fair enough
Hey guys, I need some help with a problem the easiest place to start is asking if something is changed about the data when something is stored as a "string" compared to being used as ("say something");
So I have a script that types out text that I have as a queue, I added a list to the script and when I add the strings from the list to the queue, for some reason it doesn't type them.
and i assume you call a function to also type out text from the queue?
like i dont really understand what your asking maybe im missing something
send the code maybe
Okay, I guess I'm terrible at explaining. I don't know how to format script in discord
I was kind of just hoping someone had an answer about strings
we cant know what to answer if you dont explain it well
You're not being specific at all so nobody can help
The problem might not be about strings at all, it might be about the logic of the script that is wrong
Well the question was do strings store data differently to straight out typing the string in a variable? Because that is literally the only thing different between the scripts
It's being stored the same
Something is wrong with the logic you applied but you're not giving any insight into this and I don't have a crystal ball
Not sure if this is the right channel to ask things 😅
But i've made a chess game and I would like to be able to save the game at the end and then be able to watch a replay of saved games. Is there any good tutorial I can follow to figure this out or is someone willing to help? Thank you in advance!
There are tutorials on how to save data but the other part of your question is very specific so the chance of finding something about this is very small
If I can make a suggestion, I'd say figure out first how to save things. Then find a way how you're going to represent the data you want to save. In theory you probably want to store information about every piece on the board and the moves it has made in a chronological order
If this helps, it doesn't have to be like a video. Replay could possibly be like an iteration over the moves
Yes I was thinking something like that myself and that would be the easiest way imo
Yeah, that's kind what i want to achieve
A video would be far more difficult and less intuitive than how replays actually work in video games
Two simple ⏪ ⏩ buttons and it goes through list, and as you go, the moves change
Saving data isn't the hard part itself though, it's how you're going to represent it is what might take some time to get down right
Even games like Dota store replays as commands taken per tick
thought so, any suggestions? I think the move list would be sufficient in this case?
theres the code, it's pretty basic so it doesn't leave a lot for me to guess at, the only real difference is me adding strings to the queue compared to straight up enqueing("");
Yeah probably for each move store which piece it was, it's initial position and it's target position, maybe even store how much time it took before the move was made if you want to be able to do a real time replay
both examples that i tried with string variables don't work, for some reason it just doesn't read strings coming from the queue
they get added successfully to the queue, though.
@buoyant spear You don't show what the typer does
and the list works fine?
yeah i am basically already doing that, just writing it on the screen
Alright then you should be ready to find out how exactly you're going to save the data. You can save it as text such as JSON or XML or save it as binary files
I'll probably return here once i figure the save first 😂 for some help with the loading
The loading shouldn't be much more difficult than the saving
I meant replaying 🤦♂️
your idea seems solid, honestly
@buoyant spear just an idea from me. Do that with scriptable objects, it will make your live easier.
public class ScriptableDialogue : ScriptableObject
{
public string DialogueText;
public string TalkersName; // Or just use another (scriptable)object reference that holds image, name etc.
}
public class ScriptableConversation : ScriptableObject
{
public ScriptableDialogue[] Conversations;
}
// your manager script
public Conversation : MonoBehaviour
{
public ScriptableConversation conversation;
public Queue<ScriptableDialogue> dialogues = new Queue<ScriptableDialogue>();
void Start()
{
foreach(var dialogue in conversation.Conversations)
{
dialogues.Enqueue(dialogue);
}
}
}
OR if you don't reuse dialogues some where else just use normal class:
[Serializeable]
public class Dialogue
{
public string DialogueText;
public string TalkersName; // Or just use another (scriptable)object reference that holds image, name etc.
}
public class ScriptableConversation : ScriptableObject
{
public Dialogue[] Conversations;
}
// your manager script
public Conversation : MonoBehaviour
{
public ScriptableConversation conversation;
public Queue<Dialogue> dialogues = new Queue<Dialogue>();
void Start()
{
foreach(var dialogue in conversation.Conversations)
{
dialogues.Enqueue(dialogue);
}
}
}
The pro is you can configure the asset in the asset folder directly without working on the scene itself.
I like to display dialogue in an editor graph, because when you introduce choices into something like this you'll end up with a horrible list to edit (though a graph can get equally messy)
Should be possible here too I think. I never made a graph but for my own event system I would like. Had no time yet for it.
I used XNode to make mine (https://github.com/ThePatchWorkDev/DialogGraphs), but It's definitely not the best code that can be found
Especially since it was built for a text-conversation kinda deal- rather than full on animations and storyboard
Anyone getting this error in 2020.3.21f1?
ArgumentException: Could not find item with id: 0. FindItem assumes complete tree is built. Most likely the item is not allocated because it is hidden under a collapsed item. Check if GetAncestors are overriden for the tree view.
Happens whenever I double click on any item in the Hierarchy. It's triggered by the FindItem call.
Only happens in a specific project.
git clean didn't work.
Affects all scenes.
@regal olive try resetting your layout.
"reset all layouts"
It's also possible it's coming from some custom editor window
I've never seen it, but I'm not on that specific patch version of 2020.3
okay, that fixed it
what a weird bug
It's just some bug in the editor UI
rip
well hello i have returned. i've achieved the saving and loading and now it's the matter of making the replay/autoplay/rewind w/e functionality.
@minor girder just saving a list of moves should be enough to recreate the game that was played. I've even seen chess games where you could take back moves and change to something else. The only way to recreate it this way though is to do it turn by turn, which should not be difficult.
yeah, i've saved the move list , now i need to figure out how to make it play move by move
well you could do it by using the same functions you use to move your pieces in the game, but supply the information from the move list
yeah, i'm looking into that, just thinking should i do it in a separate scene maybe?
probably for loop with a coroutine
not sure what do you mean?
I would say not a loop because you want to be able to do one step at a time.
I would have an index variable for your moveList, int currentMove and then have it so your move method for when a player moves, make it so it can take parameters that would be supplied moveList[currentMove]
yeah, i don't think loop would work as I would need to go in both directions
Thanks for the replies, and sorry for the very late response, had to dip out for an emergency overnight. I couldn't find anything related to deserializing into an existing object, but I'll dig deeper. Thanks
When I think about it more, it's not terrible to have one of these messages floating around for the life of the item that it's pointing to. The overhead is really tiny (like 10-20 bytes) and they'll get GC'd when the underlying item is discarded through gameplay, so it's ... gonna just be fine, I suspect.
@minor girder : One design pattern I've implemented for my game is the concept of a "BattleAction" (with a number of derived classes, each for one kind of battle action) that, if played in order, could recreate a game state entirely from the starting state. You could probably do something similar to that, if you needed replay/rewind/etc functionality.
My use case is a tiny bit different than yours (I use the battle actions instead of just sending the "game state" because I want to animate the actions one by one) but .. you could have rewind functionality pretty easily with an approach like that.. Additionally (and this is giving me feature ideas for my own game) you could pretty easily save the entire game and play it out later
I do have the ability to send the comprehensive game state but I don't do that often (only at the start of a battle and on-demand while developing and debugging state desync issues)
(the comprehensive game state for my game is 1700 bytes or so - too large to send repeatedly - but each battle action is mostly 20 bytes or less, when serialized)
could recreate a game state entirely from the starting state
That is something I need! I am saving a list of moves from start to end and I want to be able to "watch" the game move by move
OK.. lemme prep some source code and toss it in pastebin for you so you can sorta wrap your head around how i'm doing it for my game
Just one question, would it be possible to modify it to go backwards and forwards in the moves?
bear in mind I'm using MessagePack for serialization so there's some attribute annotations in there you might not recognize or whatever, but the basic idea is that i'm just serializing it into a byte[] and deserializing it on the receiving end
i mean, probably? i just haven't built that into my game - that's some logic you'd need to figure out and build for yourself, depending on your game
is the game multiplayer?
my chess? yeah, but local mp, no AI implemented
I meant Sharping's (i'm curious why there's that byte serialization/deserialization phase). You probably won't need that if you're doing local MP, unless it's serving some other purpose which would be interesting!
yes, my game is multiplayer
i just grabbed these snippets super quick, if you have any questions, don't hesitate to ask
https://pastebin.com/j389Hd4X Battle Actions (things the server has decided "happened")
https://pastebin.com/rvPkFw2g Player Actions (things the player(s) have indicated they want to do)
https://pastebin.com/aWXgQPSc The primary server processing dispatch - this takes the PlayerActions and "does stuff with them"
https://pastebin.com/P9Agw4Z5 The client side processing dispatch - this takes the BattleActions sent by the server and "does stuff" - animates, updates local state, etc
lemme take a quick snap of gameplay so this maybe makes more sense
Basically a player can move grid items around on their grid to try to merge them up into stronger items; move items onto their field where they can attack enemy crew (which is how you win), use active abilities, etc
thanks for sharing this btw! hard to find real implementations for stuff out there
but it's all based on a series of Player Actions and Battle Actions modifying a Battle state object
theoretically i could rewind/fastforward/replay an entire battle with just those items
pardon the developer art 🚧 we're still hiring our UIUX and art guys
I will def share mine once I figure mine out
seems like something people could use
I appriciate this a lot kind person! I will look into it later!
@minor girder maybe look into the command pattern with an undo/redo ability
What would be the 'best' way to access items from a collection in a random order without getting the same item twice?
I can think of several ways, but was hoping for some insight.
I could generate a random int between 0 and Count, and keep a HashSet of the indexes already used, checking if it already contains the generated number, if it does, regenerate it. This feels more like a brute force approach though.
Could generate a random int between 0 and Count, removing that item from the list. However this doesn't let you 'start over', so if I wanted that I would need to keep a second list that the items are added to once they are accessed.
The only other thing I can think of is maybe some type of cool math thing that I don't know about?
I think generally you would make a 'deck' of selections and pull out items as you go. This also lets you add more of certain items to tweak their rarity.
It depends what you need for your game, really. You could also keep track of how often each option has come up and increase or decrease its chances based on that
So you mean 'pre'randomize the order of the items in the collection, then get them linearly?
yeah, build a deck and shuffle it
then draw as many cards as you need
ultimately it's more of a design question than a code questoin
Right, I'm not looking for probability based randomness. Just straight up plain randomness.
then i'm not sure what you're looking for i guess
My specific use case is that I have a number of flowers on a GameObjec that can be eaten by a creature, I want to just select which flower to 'eat' randomly.
but you don't want it to eat the same flower twice?
Exactly.
why not?
Because it has been eaten...?
ah, so your problem has nothing to do with randomness, and everything to do with keeping track of which flowers are available to be eaten
No, please reread my original question. I want to randomly get an item from a list, but never the same item.
are you sure?
it's not that you don't want the same flower twice...it's that you only want to eat flowers which aren't already eaten
you should have a list of flowers which are edible and a list of flowers which are eaten, and you can pull from one and place in the other accordingly...or you could have a list of flowers with some kind of eaten boolean which you toggle, and filter them before selecting
regardless, your 'randomness' should just be 'select a flower from the list of edible flowers' and the thing you need to decide on is how you want to manage that list
That is one of the things that I said was an option in my original question...
right, which is why i said i'm not sure what you're looking for
you asked what the 'best' way is, so we talked about some of the context around what you're doing...but there is no 'best' without some more explicit values to judge against
whats the problem with shuffeling the list once and then getting them in order?
There is nothing inherently wrong. The problems I see with it is that adds additional overhead to each instance, and if I wanted a new order the items would need to be shuffled.
solutions always have tradeoffs
it's not a difficult implementation to swap out either way, right?
i guess the answer to your question is 'it probably doesn't matter'
Right, I know there is no actual best way. But I thought it seemed fun to try to make a really efficient system, even if it ultimately doesn't have that much impact on performance really.
that's cool, but the most efficient system is always the one that fits into its context most efficiently
that's kind of what i was getting at originally
the most efficient representation of this is the one that your game already needs to have for gameplay reasons
because you need that anyway
optimization is something you do for specific cases because otherwise...what are you optimizing for?
so we need to build those specific cases first
maybe @compact ingot will have a random formula for your case 😂
...But this is not a complex situation, it is pretty textbook for 'access random unique index in collection'.
Haha, maybe they will, they seem to know these types of things.
if you eat a flower, shouldnt you take it out of the collection?
or is it still there
i just built a quick randomizer for a list if you don't care that the list stays sorted
You could shuffle your list then just eat and RemoveAt(0)
It is there, but dead, and I think I will want to allow the player to 'regrow' it so I don't want to lose it completely.
List<GridItem> ret = Enumerable.ToList(_gridItems.Values);
var count = ret.Count;
var last = count - 1;
for (var i = 0; i < last; ++i)
{
var r = NumberUtils.Next(count-i) + i; // 0-9 on first call with count=10; 1-9, 2-9, 3-9
var tmp = ret[i];
ret[i] = ret[r];
ret[r] = tmp;
}
(replace ret with your list)