#archived-code-advanced
1 messages Β· Page 136 of 1
Also losing the switch expression string x = someVar switch { ... }
Was introduced in C#8
yes, i love that, btw, and use it a lot already on my server
I don't know if everyone thinks that this is the cleanest but it has saved me a ton of vertical space
Person activeCrewOfActivePlayer = (isC1Active, b.C1ActiveCrew, b.C2ActiveCrew) switch
{
(true, 1, _) => b.C1Crew1,
(true, 2, _) => b.C1Crew2,
(true, 3, _) => b.C1Crew3,
(false, 1, _) => b.C2Crew1,
(false, 2, _) => b.C2Crew2,
(false, 3, _) => b.C2Crew3,
(_, _, _) => null,
};
something like that would require a bit more nonsense if/elseif statement checking and assignment
Yeah that tuple pattern matching, beautiful
or assigning multiple values at once using tuples:
(int crewPosition, string who) = (isC1Active, b.C1ActiveCrew, b.C2ActiveCrew) switch
{
(true, _, 1) => (1, "C2-1"),
(true, _, 2) => (2, "C2-2"),
(true, _, 3) => (3, "C2-3"),
(false, 1, _) => (1, "C1-1"),
(false, 2, _) => (2, "C1-2"),
(false, 3, _) => (3, "C1-3"),
_ => (0, "_"),
};
(so "friendly" messages to the console and/or players look like this)
s += $"{who} does {damage}HP damage, bringing {target} from {activeCrewOfInactivePlayer.CurrentHP}HP to ";
activeCrewOfInactivePlayer.CurrentHP -= damage;
s += $"{activeCrewOfInactivePlayer.CurrentHP}HP";
anyway.. β€οΈ switch expressions
That's partly the reason why I don't like C# and its approach to e.g. lambda args - it's so unreadable.
no, you have to write it against netstandard2.0
you have to modify the projects to target netstandard2.0 as the framework
yeah, i'm in the process of bringing this all back to a 4.7.2 DLL
I'm hopeful that setting the <LangVersion> to 8 or 9 will compile a framework DLL that still works
i really do like pattern matching and switch expressions
https://sergiopedri.medium.com/enabling-and-using-c-9-features-on-older-and-unsupported-runtimes-ce384d8debb seems to indicate that it should be all good
you can use later c# language features on netstandard2.0
oh?
you should target netstandard2.0 as your "Framework" option in the project settings
with regards to the Api Compatibility Level* setting in the player settings, in 2021.1 and earlier, the most robust option in netstandard2.0
in 2021.2b6 and later, in practice all external library usages are broken until some bugs are fixed
yes, it's very confusing
.net standard .net framework .net core
I saw "2.0" and assumed that .net standard 2.0 was outdated or similar to .netcore 1
no
yeah .. like i said, this terminology is .. a bit triggering for me
yeah the unity api compatibility level makes it seem like netstandard2.0 is "less" than .net 4.x when the truth is the other way around
the way C# 9 features are / will be supported on 2021.2b5 and earlier is by adding a dll
oh that's funny
they even say 2021.2.0b6 in the microsoft doc
yeah, i don't mind if c# 9 isn't supported in unity for scripts (i mean, it would be nice but it's not critical to me).. but i really am going through a lot of effort to get my shared library DLL in place, as most of my code lives there.. and it would be nice if it supported c# 9+ features and worked in unity without too much headache
yeah, I saw that, and I'm in unity uh.. 2021.2.x
but I can try 2.0 and see how that goes first
you're using the beta version?
I haven't upgraded in a few months but I don't have anything blocking me from doing so
you sure you don't mean you're in 2021.1?
okay
Why? what's going on with .2?
ah.. will stay away from that then
I really don't want to be dealing with this π Have enough normal code/configuration to write! π
Error NU1202 Package Redzen 12.0.0 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package Redzen 12.0.0 supports: net5.0 (.NETCoreApp,Version=v5.0) ISG-Shared-Standard D:\projects\ISG\ISG-Shared-Standard\ISG-Shared-Standard.csproj 1
sigh
I β€οΈ redzen, too
wonder if I can just compile a version for standard2.0 myself
if it's your own source sure
if you had it working before it's compatible
It's not my own source.. it's a c# library that I use some numeric stuff from, but it depends on .net 5.0 and apparently that's incompatible with standard 2.0? i'm not sure why... this page says that it should be? https://docs.microsoft.com/en-us/dotnet/standard/net-standard
redzen is https://github.com/colgreen/Redzen
this is just giving me a headache...
hard to say
@misty glade just use version 9.1.0
aye, thanks
I tried grabbing the source from the latest version and compiling it myself but there's too many dependencies to resolve
and of course the features I'm using are > 9.1.0
lol
the features I want were checked in on July 26 2020, and 9.1 became 10.0 just a month earlier
ripped the redzen stuff out (with a tear in my eye) and put it back on the server, nugetted what I need and
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
now to see if this DLL works seamlessly in unity as a plugin
yow,
can anyone explain this?
How does that method get 0 as input as the debug clearly shows its not
Am I just missing something obvious?
targetFollow.FollowSpeed is 0
Well I agree, but if you look at the if statement if distance is greater then 1.5 which it is as the debug log shows 2.2
It should use the Default one ?
if the distance is greater than 1.5, then FollowSpeed will be used .Otherwise, GetDefaultSpeed will be used. You printed out GetDefaultSpeed, which is not being passed to the method
condition ? true expression : false expression
I see rip, thanks
Not sure exactly where to post this question, but which would be more efficient. A prefab with 45 different tile geometry states and setting them active / inactive based on neighbors updating. Oooooorr 1 mesh filter with a list of 45 meshes, and set that 1 mesh filter to the right mesh on update
(basically think a 2d tile set but with 3d geometry)
or if there's a wonderful 3rd way i'm all ears
So I have a pretty advanced section of code
and Ive optimized it three times
to the point where I am using a hashmap (dictionary in c#) for item lookup
it has to do with the way my game is generating item from a lootbox
essentially a "Lot" (lootbox) has a spawn pool of items that can be in it
and a number of items you get from opening it
so im mapping the items to a dictionary with <float,item> where float = the upper bound of the spawn chance for each item incremented as we go
so for example if I have a spawn pool of items that looks like this
itemOne 50%
itemTwo 50%
then my hashmap should look like
50 : itemOne
100: itemTwo
because item two has a 50% chance on top of the 50% of its predecessor, which sums as it goes
I then create an array of dicerolls from 0 to 100 using random.range(0,100) and sort that array
then for each slot in the diceroll array I retrieve the item that is in the dictionary for its upper bound in the spawn chance array
ergo if the diceroll was 35, which is below 50, I retrieve the item for 50 in the dictionary, in this case itemOne
I then do this FOR EACH LOOTBOX that was purchased
to summarize, make a map of spawnable items by summing spawnchances and making that summed spawnchance the key in a dictionary of <float, item>
then perform dicerolls * the number of items you should receive, and the closest number to your diceroll is the item you receive
the problem is that if the player buys like 20 lootboxes, this code can take around 10 seconds to execute
does anyone have any further optimization suggestions
Feel free to ping me if youd like to discuss the code as I know this is complex
https://en.wikipedia.org/wiki/Categorical_distribution#Sampling this is how you sample from a categorical distribution, which isn't really a lootbox btw
thanks ill give it a good look
lootboxes are drawing without replacement
so if you want it to behave like lootboxes, you need to do drawing without replacement
that means it behaves like a deck of cards
yeah this is drawing with
https://en.wikipedia.org/wiki/Hypergeometric_distribution#Properties this is a good formal description of what is going on
@quartz smelt you can also use this https://numerics.mathdotnet.com/api/MathNet.Numerics.Distributions/Categorical.htm which has an efficient version of the categorical sampling
sorry if you want to not make it take 10s to execute you gotta use the right thing you can't just hack it together
i don't think it will matter either way, as long as the tile geometry is simple
thanks. Follow up question, does it matter if every tile has the the same list<> of meshes, or should i have some kind of tileset manager so there's only 1 List<> that all the tiles grab from
it won't really matter eithe rway, but probably the later is simpler to implement
it sounds like you are reinventing unity's tilemap
you probably just want to use a prefab
for each tile
you can model the different tiles as a prefab variants
then, use unity's tilemap
wow can I get this without a side of snide next time?
i'm sorry π i meant that to encourage you to look into some cool new stuff
and not feel overwhelmed
if you feel like you looked at "Sampling" and just felt like "okay this doesn't help me"
it does
you will see that you were halfway there
the hard part is using the binomial
meta question; what is the difference between an advanced coding question and a general-coding one? (I guess whats the cut off or is there a gray area here)
aighty. I was going to ask about how something like Slay the Spire or other turn based games handles effects parsing/order, but I'm not 100% sure if that's a general question since it's vague or advanced since there's not any 1 way to go about it.
when it doubt just use general
I'll take it to general then and see, tyty
my doubt is that I wanna make a combat game (2D)
& I wanna make it multiplayer
but I also wanna add slow motion
I want advantage or disadvantage cause you need to unlock these powers & to unlock you need to dm me for code to unlock
these are my ideas for making worst game ever
issue is that how do I make 1 character move in slow motion & 1 character will see the other character in very fast motion
like happens in real time
uhh
I dont know if you guys understood cause my english is a bit weak
You can't slow time for someone awhile accelerating it for others while they interact with each other, that's physically impossible
oh π¦
What you can do is slow down everyone while one is unaffected
The effect will be the same
oh yeah
But the players who were slowed down will know that someone is faster than them
hmmm
I only mentioned that because your original intent was that players always moved at "normal" speed from their POV
But that's impossible, the closest you can achieve that is having one of the parties with altered speed even from their POV
Hey guys, I hope this is the right channel to post this in! I have a video of my problem too, I am just not sure if I am allowed to post it here π
I have a very strange problem happening. I use a VideoPlayer in my UI and it works actually pretty nice.
My game is split in a pretty low performance part and a more demanding part.
The videos play super nice and smooth in the first part but they barely play at all in the second part. That's the only thing I was able to say for sure.
It's all mp4 videos, 2,5kbps, 1280x720, no audio.
I tried using videoPlayer.Prepare() in multiple different ways and awaiting the callback too but this didn't change anything unfortunately. It seemed like it starts preparing the first 10-20 frames over and over again.
Does anyone have an idea what the cause might be here? I'm releasing on Monday so this is pretty urgent for me haha! π
Thank you so much in advance!!
whatβs the math behind scaling resolution and uiscale at once?
(posted in beginner but no one had a answer trying here)
You need to be a bit more specific
I want to scale my ui with resolution and uiscale
But I want to know the math behind it
the math is unity internal so Iβd have to reverse it
have you tried a different video that you did not encode? for example, a video from youtube?
You mean using a URL instead of a local file?
why can't you use unity's ui scaling
no, i mean a local file
but one that you didn't create
No I haven't, I'll try that.
Unfortunately it is the exact same issue. I can load and watch any video in the first part, only the first few frames in the second part of the game.
then you need to make the second part of that game faster
it's unavoidable
there's nothing wrong with the video player
So you think if I just speed everything up 500x, the video will be smooth? π€£
are you saying slow as in time scale or slow as in performance?
Performance - the time scale is not touched. Between those 2 parts nothing changes at all, other than the game play focus and a couple of UI elements. It's the exact same scene, same save game, same everything. That's what makes it so weird for me and why I am so clueless on where to start looking for a fix haha
But I am not even close to maxing out my RAM, VRAM or anything on my system
Hey guys, do you have an idea how to make a loadbar (non UI elemnt) ingame? Like showing only half an object when a float is at 50%
With a shader that lerps a mask
More of a vent than a question, but why do the overloads for GetComponent - that take in a list instead of returning an array - clear that list everytime you call those methods π€, now I have to have two lists and copy from one to the other between operations
And why do Awake & Start methods not get called for disabled objects anyway, I'm in this whole mess because of that basically.
I have Awake & Start methods on disabled UI game objects and I need to invoke them with the rest of the active game objects
You can simply make a custom init method in them and call that from a active awake/start. The monibehaviour methods are not supposed to run on disabled objects by drsign
I also saw that constructors were run on disabled objects, might be of use
if it didn't clear, how would you differentiate between components on the object you called it on and results from a previous operation?
as for this - can't you just put the visible elements in disabled objects and leave all the logic etc.. on a separate GameObject that is not disabled?
Is there a way to make a child collider, trigger the on trigger events from a parent object?
i have a bunch of sub colliders that all have the same functionality. im trying to call on the parent object (On trigger stay) and have the collisions from the sub colliders trigger the event
does anyone have an idea?
basically i want to detect the collision on the Sub Colliders but have them all act collectively and pass the collision up to the parent object
yes this is basically the default behavior
you may need to have a Rigidbody on the parent though
(it can be kinematic)
Calling ontriggerstay on the parent ignores the child objects and only takes the collision directly related
ahhh i need a rigidbody
You don't "call" ontriggerstay
By keeping track of the list count after the previous operation, or by simple clearing the list myself, forcing a clear is just limiting for no reason
is there anyway to get around that?
And have one script on the parent. Then all child colliders will trigger up the chain. If you have a script on a child it will eat the msg
there are a few APIs in the Unity api that do work like that, e.g. https://docs.unity3d.com/ScriptReference/Physics.OverlapSphereNonAlloc.html
but currently they don't even return the count
so you couldn't
anyway is it really a big deal?
Clearing <10 elements from a list is nothing
unless you're doing some crazy thing like having hundreds of components on the object?
I have the script on the parent object (Hitbox) checking for "OnTriggerStay"
then the children objects all have a sphere collider and are positioned NOT OVERLAPPING. I added a rigidbody and tried again but still no collision being detected
I could but that honestly that seems like too much to maintain, for now I implement an interface that has Configure & Initialize methods that work like Awake & Start respectively, I query & invoke components that have those interfaces when scenes load.
Works well enough.
It's not a big deal really, but so many of these small things stacked up so I wanted to vent π₯²
Are the colliders marked as triggers?
yeah
Hitbox is the parent object, then there are 3 subcolliders as children, each holds a sphere collider marked with trigger
private void OnTriggerStay(Collider other)
{
Debug.Log("sucess");
}
^ this is the only code that is attached to the parent script
Maybe it needs to be public to get called
it doesn't
can you show inspectors for the two objects you're expecting to trigger each other?
Yeah was just spitballin here it should work from what you are telling us
even when i add a rigidbody i dont get any messages
would it be bad practice to make a method on the parent object "CollisionDetected()" and then on the sub colliders use OnTriggerStay(){hitbox.CollisionDetected()}
is the game running?
yeah
is the cylinder actually overlapping the sphere?
yeah im moving it over all of them
in play mode i drag the capsule over all the colliders
Hitbox has the script
Rigidbody is on the parent of hitbox
put the script and the rigidbody on the parent
on the same object
GameObject(1)
or whatever it's called
yeah that worked!
thank you
Is it going to matter if i have random Rigidbodys on my characters though? in the actual game i use Character Controllers and physics is driven by Code which is why i didnt use rigidbodys in the first place
if you make the CC kinematic you're fine
sorry
the RB
if you make the RB kinematic you're fine
ok so Kinematic basically just disables the rigidbody?
it makes it so the body isn't affected by forces or collision/impacts and is instead fully controlled through scripting.
so would it be bad for performance if instead i make a method on the parent object "CollisionDetected()" and then on the sub colliders use OnTriggerStay(){hitbox.CollisionDetected()}
so bascially each sub collider will check for collision on its own and then call a method on the parent object
that way i dont need the rigidbody and i can grab the specific collider that was hit also
it sounds like you have something else going on in your scene that is making this not work well
it's going to be some bug in your stuff
which isn't saying much
if you need the specific collider that was hit this is basically your best option
but it doesn't sound like it's the video or video player
i think you have to start with some more unity training or maybe find an asset store asset that does what you are trying to do
if you need to run code on a disabled game object, move the code to an enabled one
I mean im not new π€£ I have quite a bit of experience this is just new to me
Must be but there's nothing new added, the only thing which is changed is that the nav mesh is being baked
you gotta throw me an #archived-code-advanced bone here
right now it sounds like there's just a kitchen sink of stuff going on in your scene
what is the game, what is going on with the video, etc.
maybe show a snippet so we know how well you program
I'd love to. π
Are links allowed here?
yes but a video is very uninformative
i think you can just write what is going on
in the game
like why are you playing a video?
why are you baking a navmesh
what is the gameplay
I'm getting the following error on build to PC:
System.Windows.Forms.dll assembly is referenced by user code, but is not supported on StandaloneWindows64 platform. Various failures might follow.
With a rather unreadable and large stack trace: https://pastebin.com/xpkN7EdR
Do I need to be worried? App works fine as far as I can tell, no other errors, runtime or otherwise..
Ok so:
The game is a festival tycoon game. The player starts in build mode (where the video works) and continues into live mode (where it doesn't work).
The transition form build mode to live mode is basically just a loading screen, a lot of nav mesh stuff behind the scenes and UI updates. No scene change.
This is the bug: https://youtu.be/6PqCQydcRy8
This is the code for the video player, Play() called whenever the overlay opens up (see video).
public class UI_VideoPlayer : UI_Element
{
private static event Action<UI_VideoPlayer> EBeforePlay;
[SerializeField] protected RawImage rawImage;
[SerializeField] protected Image iconLoading;
private VideoPlayer videoPlayer;
protected override void AwakeIntern()
{
base.AwakeIntern();
videoPlayer = GetComponent<VideoPlayer>();
EBeforePlay += OnBeforePlay;
}
protected override void DestroyIntern()
{
base.DestroyIntern();
EBeforePlay -= OnBeforePlay;
}
private void OnDisable()
{
StopAllCoroutines();
Stop();
}
private void OnBeforePlay(UI_VideoPlayer player)
{
Stop();
}
public void Set(VideoClip video)
{
videoPlayer.clip = video;
}
public void Play()
{
EBeforePlay?.Invoke(this);
if (videoPlayer.isPrepared)
{
videoPlayer.Play();
}
else
{
StartCoroutine(PrepareVideoAsync());
}
}
public void Stop()
{
videoPlayer.Stop();
}
private IEnumerator PrepareVideoAsync()
{
videoPlayer.Prepare();
iconLoading.gameObject.SetActive(true);
while (!videoPlayer.isPrepared)
{
iconLoading.transform.Rotate(Vector3.up, 25f * Time.deltaTime);
yield return null;
}
iconLoading.gameObject.SetActive(false);
videoPlayer.Play();
}
}
Where's the iconLoading gameobject? Not that that's the cause of anything, just trying to understand it all
I'm wondering if maybe your videoPlayer.isPrepared boolean isn't working properly?
It's just a GO to have something moving while loading, it's on the video player
(I'm assuming you're calling Play() on mouse enter)
Like - if a video isn't prepared and you kick off the call to PrepareVideoAsync() twice, what happens?
It is, I tried with the debugger attached and I also added a callback to all the events which do not give any errors, frame drops,... but it triggers the prepared event
Kinda, yes. It's IPointerEnterHandler
Yeah, that's what I meant.. hmm
I think the code you've pasted looks reasonably correct? I imagine maybe there's some bug with how you're calling play or preparing the video..? It seems as if it's playing for a very short time sometimes - like 1-2 frames..
Like how is OnDisable() being raised?
The weird thing is to me that this seems to work without any problem, I do not have any issues in the mentioned part of the game, only later on and then they're always appearing, without exception
What's always appearing..? the bug?
I tried that too with comments, play is called once and stop is called once too
yes, the issue with only playing ~10 frames
So maybe a trick to debug this is to add a debug hotkey - whatever, like F1 or somethign unused, and when you experience the bug, press F1, and tie that to a console dump
And list all the things like.. videoPlayer.isPrepared for the current video, number of coroutines running on the GO, etc
Since you can't just breakpoint the coroutine (since it sounds like it's working fine normally)
even just make sure the Set() is properly .. working.. like output videoPlayer.clip.name or some property that identifies it, if you have it
and obviously I'm assuming your AwakeIntern() method is ... only getting called once, at Awake() or something else
(so you're not subscribing twice to the event handler on accident)
Yeah, I'll probably try something like that π
It's called at awake(), just once but I'll double check that!
I can but I wanna know the math behind it
You can either have test methods or debug methods - they tend to look the same - and you can tie into the debug messages with hidden hotkeys or buttons that only show up in debug mode. I like to make a little panel with debug buttons that I can show/hide depending on whatever I'm doing in the development process
(it also contains a simple panel with a textmesh element in it and my logging library outputs to that as well so I can see the "console" output even in the windows PC mode, if i need to)
Yes, I do have that too π
I'll double check the event and if that's fine, I'll do a print thingy haha π
Thanks a lot in the meantime!
No worries.. sorry I couldn't find an obvious bug
I suppose in this channel that's going to be status quo... brainstorm together to find obscure bugs
there is a lot going on here that makes me skeptical
lots of code smells
for example, OnBeforePlay calls Stop(), there's an AwakeIntern idea, the coroutine
have you tried just using hte profiler?
it'll tell you
what is slow
hi guys, what is the best data base to use for a mobile game? I have a multiplayer game project, but some stuff i dont know where to begin and are my biggest issues at the moment, like the data base and the authentication with the play store, any recommendations?
I have a worldspace canvas with some buttons. Each button has an additional canvas that should load (be active) everytime I hover my mouse over it (see figure). This is not happening. Any suggestions on what I can change?
Here's a basic code:
public class ShowAdditionalUI : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
[SerializeField] Canvas additionalCanvas;
public void OnPointerEnter(PointerEventData eventData)
{
additionalCanvas.enabled = true;
}
public void OnPointerExit(PointerEventData eventData)
{
additionalCanvas.enabled = false;
}
}
WorldSpaceCanvas with additional canvas
Secondary canvas when active.
Secondary canvas when active.
one common error with this kind of setup is that if the "hover" canvas is itself a raycast target, and it pops up directly under the mouse, it will block the underlying object when it becomes enabled, thus immediately triggering the OnPointerExit
are you having that issue?
Let me check.
otherwise - check the standard event system stuff:
- make sure nothing is blocking the object you're trying to hover
- make sure you have an EventSystem in the scene
- make sure your canvas has a GraphicRaycaster
- make sure the event camera is set on the canvas
- make sure you have an InputModule on your Event System
No. I think because the canvas is towards the side, it is not a problem.
Yes, I wrote in more detail what I did over there: https://forum.unity.com/threads/video-player-on-windows-freezes.1173638/
The event is really just a trial and error thing, it works but it's not necessary I think as it doesn't change anything in the part of the game where it works.
The OnPointerExit method does not get called when I'm still hovering over the button. But I don't see the secondary canvas.
is the OnPointerEnter being called?
Yes
From your screenshots it looks like the whole GameObject is deactivated
but your code is dealing with enabled/disabled for the Canvas component only
did you mean to do additionalCanvas.gameObject.SetActive(true);?
This solved the problem! Thanks! So the difference basically is that my code just enabled the canvas. GameObject also enables the children.
not just the children. The actual GameObject
Circling back to this. I see a potential problem with the canvas gameobject immediately being inactive once I navigate to the new canvas. Any suggestions to solve this?
hmm that's a bit tricky
if the new panel is a child of the one with the script on it - does that work?
Nope.
I think I figured it out. I can explicitly add a button to close it inside; from the secondary canvas.
hover effects are pretty complicated. this will glitch even in the editor
it looks like you are trying to build world space UI which is sort of a bad idea. the best thing to do is use only one screen space canvas, but position its elements based on the world space objects they are "tracking"
In what way is building a world space UI a bad idea?
i don't know if having everything in one canvas is a good idea, that seems like a tough organisational thing
the canvas also needs to refresh everything every time one element is updated
The problem is that, when one or more elements change on a Canvas, the whole Canvas has to be re-analyzed to figure out how to optimally draw its elements.
https://unity.com/how-to/unity-ui-optimization-tips#divide-your-canvases--2
so splitting canvases is a good idea
you should use only 1 canvas
world space UIs are hard to make look nice
the costliest part of rendering in UGUI is text
canvas hijinks will not change that
if (up.GetComponent<TileWall>().GetTileID() == 2)
{
Debug.Log("UP is Wall");
var s = gameObject.GetComponent<SpriteRenderer>();
s.sprite = Resources.Load("WallTopConnected") as Sprite;
}```
I'm not sure why, but whenever this is called in update the ``gameObject``'s sprite turns to ``None`` even though I have WallTopConnected in Resources
Can you show your WallTopConnected asset?
Where is it in the project and what are the import settings?
Try this:
Resources.Load<Sprite>("WallTopConnected")```
instead of the thing with the as Sprite
I don't know what it is about you, but it worked! Thank you @sly grove
I literally tried
the exact line of code
lmao
I think the problem is that if you just do Resources.Load("WallTopConnected") it gets it as... something that isn't a sprite, and then the as Sprite cast will just give you null if the thing is not a Sprite
Now to duplicate this and change it for the right, left, down, up-left, up-right, down-left, down-right, up-left-right, and down-left-right π
I see. That's sort of confusing, I was trying to follow the unity doc with this
you could just reuse the code and use an array of strings for the tile names
I was going to do if up && down == wall etc
e.g.
public string[] tileNames = {"WallLeft", "WallRight", "WallTopConnected"}; // etc...
private Sprite GetSpriteForTileId(int tileId) {
var sprite = Resources.Load<Sprite>(tileNames[tileId]);
return sprite;
}
// then later...
int tileId = up.GetComponent<TileWall>().GetTileID();
var s = gameObject.GetComponent<SpriteRenderer>();
s.sprite = GetSpriteForTileId(tileId);
so you don't need a bunch of if statements
Oh I see, so it matches with the name
I don't think I can do that with how I structured the TileBase class with TileWall in it
Anyone tried using System.Numerics.Vector in Unity 2021.2? Was working fine in earlier versions but now I'm getting ambiguous reference.
The IDE (Rider) tells me there's one in netstandard and one in System.Numerics.Vectors. Can't use either
stick to 2021.1
the beta is not reliable enough due to a weird netstandard2.1 thing they're doing
Did you copy your own DLL to unity? If so, it sounds like it's not included by default
Hi everybody, i want to change the Graphic API (DX11 , DX12) in build windows game, but i can't find a way except i build two .exe file (once with DX11 and the other with DX12) can i make it one build and give player a setting to change it in game?
I guess most games have a launcher software for that that loads the specific exe file, same es some Game32 and Game64.exe thing @fickle ether
so than the only way is to build two different version of my game? right?
I guess so. You could at least turn off auto api and set dx12 on top of dx11, then Unity will try to use dx12, if not available, try to use dx11
Not sure if you have cloud build, but this could help you do that stuff in parallel, while keep on working on other stuff in your machine.
good idea... but what if player wants to play with only DX11 to get more FrameRate or i dunno for any reasons...
so this must be the result: a luncher must made to let player chose to what version wants to play... but another problem is here, the game storage is 10 GB, so now if i build two different versions, it's gonna be 20 GB... can't i make it in one build all assets but with two .EXE files ? like one for DX11 and other DX12 ?
I don't think changing the target api would affect performance that much, if at all. What will affect it is whether you're using some new features coming with DX12, but you don't need to change the api, to turn these features off. At least that's what I think.π€
DX12 is slower in some cases, depends on the game.
I'm still not convinced. The api is just a tool. What matters is what you do with it.
I mean, his question is, how to start with different API levels. And I guess, there is no out of the box way yet
you can use playersettings to set it while building it, but at runtime, cant find a solution online yet
There should be a command line argument to force the graphics library used
Ok so I just wanted to let you know that got my video issue working. The problem was totally on my side (who'd have guessed lol) and the fix was the following:
Every time a possible step-completion condition was triggered through an event, the steps were updated. Looked like that:
steps.ForEach(s => s.gameObject.SetActive(false));
var shownSteps = TutorialManager.CurrentVisibleSteps(steps.Count);
for (int i = 0; i < Mathf.Min(steps.Count, shownSteps.Count()); i++)
{
steps[i].gameObject.SetActive(true);
steps[i].Set(shownSteps.ElementAt(i));
}
You see this steps.ForEach() ? Don't do that π
I fixed it by replacing the code with this:
var shownSteps = TutorialManager.CurrentVisibleSteps(steps.Count);
for (int i = 0; i < shownSteps.Count(); i++)
{
if (steps[i].RequireUpdate(shownSteps.ElementAt(i)))
{
steps[i].gameObject.SetActive(false);
steps[i].Set(shownSteps.ElementAt(i));
steps[i].gameObject.SetActive(true);
}
}
steps.ForEach(s => { if (!s.IsUsed) s.gameObject.SetActive(false); });
I introduced RequireUpdate(step) which checks if the step actually changed and only then set the clip. SetActive() was actually the issue. And because the live mode has a lot more condition checks, that's why it was never a problem in build mode. π
It's still a bit ugly but I don't have the time to make it nice right now, will get back to it tho (or at least that's what I say now) π
Thanks for your help tho! Really appreciated!
(sorry for interrupting haha)
you can look into this @fickle ether https://docs.unity3d.com/Manual/CommandLineArguments.html at least this way you can make a shortcut with desired values for d3d12 or 11
thank you so much friend π
That for loop is very inefficient. Count() iterates through the whole thing to count the elements, and ElementAt() will iterate from the start until it reaches the element.
If shownSteps is an IEnumerable, it would be better to use a foreach but increment your own index variable to keep track of it.
Yeah, as I said, it's a temp fix for now and it's only 26 items, there is no scaling going on. But you're right, there's definitely a better way to do that (looking at the SetActive() too)
Hey everyone
Is it possible to export convex mesh collider as .obj file?
meshcollider is basically a unity object, so I do not think so. you can convert the points into a mesh with a script or manually and save that
Is there any way to get convex mesh collider data as triangulated mesh? Or read vertices and indices from collider directly?
Mesh collider just has a Unity Mesh as one of it's fields, you can read that and get verts, indices, and probably other things
I assume that he wants to get the simplified (convex) version of the mesh that's generated.π€
Yep. To reduce the export obj file size, my aim is to keep tris as low as possible.
I don't think that it's accessible on c# side.
You could generate a convex mesh in blender though.
Is it possible? How to do that?
Sadly convex hull wraps the object from outside.
Let's say I have a 3D of house and it's one mesh, then convex hull can't create mesh for interior
Of course not. But that's exactly what happens with unity mesh colliders...
You could separate it into several meshes and then apply convex hull to them separately.
Can u run a function async with the Invoke?
Or at that point do I use a coroutine with a yeild return new WaitForSeconds.
In a sense it's already async if you call it with Invoke, since it runs independent of the place where you call it.
What you mean is whether it's possible to keep it running over several frames, right?
yea I don't want the function to block my game
Basically my game will run 24/7 on a server and has to make API calls every second. The API requires credentials that will expire after x amount of time. So i am trying to find the most efficient way to renew the credentials in the background every day
and renewing the credentials is also an API call which is why I want it async
coroutines would probably be best
Alright so the coroutine with yield return seconds then
yeah
thanks
what would be more efficient?
tbh both are kinda convoluted
I'd do just textMesh.text = TIMER_PREFIX + System.String.Format("{0:0.000}", Time.time);
textMesh.text = $"{TIMER_PREFIX}{Time.time:F3}"; gives the compiler the most info to work with, wouldn't expect the explicit string builder approach to provide any benefit in such a short string with such minimal edits.
i've always learned that using stringbuilder is more efficient ? :v
I suspect that all the extra operations cancel out the concatenation efficiency many times over.
StringBuilder is only faster on larger amounts of appends, just one append is going to be slower
Interpolated strings are just concatenated strings behind the scenes
string.Format or template strings are going to be as efficient as StringBuilder for sure. Potentially more efficient.
the answer to all engineering questions is "it depends". No such thing as "always better" in comp sci.
TEST()
{
var a = 1;
var b = "foo";
string x = a + b; // compiled to use array concatenation
/* compiles to:
IL_0010: ldloca.s a
IL_0012: call instance string [mscorlib]System.Int32::ToString()
IL_0017: ldloc.1 // b
IL_0018: call string [mscorlib]System.String::Concat(string, string)
IL_001d: stloc.2 // x
*/
string y = $"{a} {b}"; // compiled to use string builders
/* compiles to:
IL_001e: ldstr "{0} {1}"
IL_0023: ldloc.0 // a
IL_0024: box [mscorlib]System.Int32
IL_0029: ldloc.1 // b
IL_002a: call string [mscorlib]System.String::Format(string, object, object)
IL_002f: stloc.3 // y
*/
}
string.Format(...) uses and internal, cached, thread-specific StringBuilder that is reused for for all format calls. So it already does all the general purpose optimization that the OP attempted in the background.
string.Concat(...) uses array concatenation
Whichever is faster, depends on the use case. In general, the compiler does a great job of optimizing stuff like that... improving on those optimization requires detailed understanding of the IL code that the compiler produces, which again requires detailed understanding what the JIT or IL2CPP/LLVM compiler does and then again what the CPU architecture likes to work with.
try to describe in gameplay terms
what you're trying to achieve
in two sentences
@spare garden "a one coordinate system to another as two right-angle triangles due to different scaling techniques." this is hard to understand
I don't know what level of intermediary code this falls under, but how do I properly get Unity to read the alpha values from a webcam device in a webcamtexture? Seems like it's just defaulting them to 255 no matter what.
The WebCamtexture constructor doesn't seem to accept a TextureFormat for some reason, so I'm kind of at a loss.
Definitely not my area of expertise but how can a webcam have alpha values?
Virtual camera.
Specifically, I'm reading from a virtual camera coming out of another Unity application, which I can confirm is being transmitted with alpha, because OBS properly respects the alpha value when it's added as a video input source.
if (up.GetComponent<TileWall>() != null)
{
Debug.Log("UP is Wall");
var s = gameObject.GetComponent<SpriteRenderer>();
s.sprite = Resources.Load<Sprite>("WallTopConnected");
}
else if (down.GetComponent<TileWall>() != null)
{
Debug.Log("DOWN is Wall");
var s = gameObject.GetComponent<SpriteRenderer>();
s.sprite = Resources.Load<Sprite>("WallBottomConnected");
}
So I have these two statements running in an update method in a class that's derived from an abstract class type. The first if statement works fine, but the 2nd doesn't work. When I place a tile above another tile, the bottom tile changes to WallTopConnected, but the top tile stays the same
like it keeps stopping after the first if statement, it wont go to the else if
So, the second one should only run if up doesn't have a tile wall, right?
So, I'm assuming this code gets run on all tiles involved, right?
Are you sure you're not getting a NullReferenceException if up is undefined?
It runs on tiles with TileWall in it
That'd stop the function entirely, no if
Hmm
Do you get an NRE?
If it throws the error it instantly warps to the catch block
Do not pass go
do not collect $200
I see
You should probably check if up is null before doing stuff to it instead of just try-catching
try-catch isn't a magic "make errors go away" button, it still throws them
Couple points:
GetComponent()inUpdate(){}should be avoided (performance)- Dont use exceptions for flow control
- You can use
if(TryGetComponenty<T>(out T component)) {}
it just lets you do catch instead of dying instantly
You should be only using try-catch when you don't know if the exception will be thrown and which you can't priorly check against ..(things out of your control)
I'm getting a MissingReferenceException instead of NRE
Same error, different hat
yeah
You need to check if up exists before you try to get component on it
I get the MRE on line else if (down.GetComponent<TileWall>() != null)
instead of the up one
Then down isn't set on something
up is defined as
up = GM.tiles[Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().x), Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().y + 1)];
so I guess I'm double checking an existing component
no nvm
basically GM is class of GridManager
the GridManager generates tiles of gameobjects in a grid with TileBase added
So I would reorganize my code to:
if (up != null)
{
if (up.TryGetComponent(out TileWall tw))
{
Debug.Log("UP is Wall");
var s = gameObject.GetComponent<SpriteRenderer>();
s.sprite = Resources.Load<Sprite>("WallTopConnected");
}
}```
might as well also cache that Resources.Load somewhere
or not use Resource.Load in the first place
Cache your SpriteRenderer. There's no reason to get s every time
And the Resources.Load call too, store the sprite for each wall type and only call Resources.Load once each
can't you make the sprite an editor reference?
if (up != null and up.TryGetComponent(out TileWall tw)){
renderer.Sprite = TopConnectedSprite;
}
Doesn't that look much cleaner?
Renderer would just be
''var renderer = gameObject.GetComponent<SpriteRenderer>()''
Above the if statement
Cache it in start
Why do it in this condition?
It never changes
For anyone who's been following along at home with my headaches the last few days, I have shared libraries with dependencies working pretty smoothly now, so I thought I'd take a moment and outline the process if anyone wanted to reproduce it for their own projects. Feel free to DM me, there's a lot of details that are important.
The requirements for me were to make as "least-fragile" a solution as possible for a shared codebase (client in unity, server in !unity).
- Make a new project in MSVS of type Class Library (.NET Framework). NOT "Class Library" (which targets standard2.0 - I didn't have luck resolving dependencies with it).
- Plop your code in here, and edit the post-build script macro (Right click solution / properties).
- In this post-build script, copy the DLL to unity's Assets/Plugins/ special folder.
- IF YOU HAVE DEPENDENCIES - it's better to import them into Unity rather than try to get all the DLLs (gotten from NuGet) included in the build to copy over to the Plugins folder as well.
- I use MessagePack, which has a separate step for generating code, so I do that here as well.
My post-build script for my shared project looks like this:
cd "$(SolutionDir)"
dotnet mpc -i "ISG-Shared.csproj" -o "$(SolutionDir)Networking\Generated\MessagePackGenerated.cs"
copy "$(SolutionDir)Networking\Generated\MessagePackGenerated.cs" "\projects\unity\Idle Space Test\Assets\Scripts\Generated\"
copy "$(SolutionDir)$(OutDir)$(TargetFileName)" "\projects\unity\Idle Space Test\Assets\Plugins\"
copy "$(SolutionDir)$(OutDir)$(TargetFileName)" "\projects\ISG\lib\"
I also copy the DLL to a lib folder in my "project" root because:
- On the server solution, you have to "import project reference" and browse to a DLL. This works great, but obviously you don't want to have to fiddle with Debug/Release directories, so doing the above copy to a /lib folder can ensure that whatever the "latest" version of my DLL is can be properly referenced on the server codebase.
Voila, you've got 3 projects - client, server, and shared - and you can (and probably should) check them into their own repos. No more duplicated code or copying code around or anything like that.
HTH
Also - NuGet for Unity does not work very well... It took me a long time to diagnose that it was unable to pull down older versions of things and was often getting the version of the dependency wrong, especially when it was strongly-typed - I was getting errors like "Assembly 5.0.0.2" is not valid, dependency is strongly typed for "Assembly 5.0.0.0"
Now after burning 3 days to this little exercise, I'm going to nerd it up with D2:Resurrected. Have a nice weekend y'all.
Interesting and as the same time... very specific. You may want to write a post on the forums. Here it will only get lost to the god of time.
So it's still only detecting the up tile
if (up != null && up.TryGetComponent(out TileWall tw)){
Debug.Log("UP is Wall");
renderer.sprite = Resources.Load<Sprite>("WallTopConnected");
}
if (down != null && down.TryGetComponent(out TileWall tww))
{
Debug.Log("DOWN is Wall");
renderer.sprite = Resources.Load<Sprite>("WallBottomConnected");
}```
I moved the debug.log after the renderer.sprite, apparently it returns after I set the sprite
Do you still have it in a try-catch?
I don't
There's no return in there. If it's ending on the renderer.sprite line it's erroring
Put a debug log before and after it
If you get the before but not the after, it's erroring
It works before, I moved the Debug.Log("UP is Wall"); after it
and it stopped printing
I might need try catch {} for this
Then it's crashing
You shouldn't have try catch anywhere
If you don't have a damn good reason to expect an error and not care, you should just let it error
It might be because it's in update, so it's continuously setting the sprite
It'll still print
hm
Put a log before and after the renderer line
if you get one, but not the other, you're erroring
and you've probably got a try-catch hiding it so it gives you zero useful information
I don't have try-catch anywhere
Well now its printing "UP is Wall" after I set the sprite
if (up != null && up.TryGetComponent(out TileWall tw))
{
renderer.sprite = Resources.Load<Sprite>("WallTopConnected");
Debug.Log("UP is Wall");
}```
And is it not setting to WallTopConnected?
wait
okay
for some reason, it's only detecting the instance it's placed down
like the 2nd tile placed in the sequence isn't updating, but the one adjacent to it is
Are you re-setting up and down after a new piece is placed on the old ones?
Anyone have some good sources on architecture for things like a tower defense game with branching upgrades? I want to make this but am unsure where to start, do people just make a bunch of classes that inherit from something like Upgrade<T> where T : Tower, and use reflection to find the upgrades, assuming upgrades change towers in ways that are more then just stats-
Lots of ways to do it...
How does reflection come into play here?
more than just stats as in texture changes too? you could use an abstract class or scriptable object
Just spitballing, I assume that'd be the easiest way to get all of these classes
since you can't drag them in unity for reference ; considering it's all done in code
I'll take any specific way of how people do it; I want to know them all so I can make a decision on what I'd like to do
feels to me like you are kinda overthinking it a bit
That's very likely
but I also don't like jumping into coding with absolutely no image of how I'm going to do something
For my game, I organize my tiles from an abstract class called TileBase
you could do something like StructureBase
best way is to build it the way you think it would work... fail, rewrite, fail, rewrite.... best way to figure it out
I know about Polymorphism, abstract classes and all that jazz, I'm talking specifics
like how specific?
What other developers did, ideally
because from that point it's up to you
definately DO NOT USE INHERITANCE
lol
:P
other than that... don't worry about language features... worry about data transformations
Well, its a tad bit difficult to explain specifics over text, so I'll try and solve one problem for you. You can't serialize generic classes, but if you inherit from them and make them concrete, you definitely can
I don't know why tile detection is so difficult to code for me :/
@queen plover an idomatic game-type thing would be to upgrade an actor/entity by adding/activating components on it that handle a specific gameplay ability
Maybe I should have an entirely separate script meant for it, so it gathers all tiles in a for loop, looping through all the tiles. Then if it has like if tile == wall, check neighbors
instead of writing it in a class that derives from an abstract class
also generally a good idea to have game state in a state-machine or something similar to avoid if/else/switch hell (i like to use https://www.nuget.org/packages/Stateless/)
depending on how "big" the game is supposed to be... aim for a data-oriented/driven architecture i.e. make behaviour configurable through the editor, use scriptable objects to share events/data... you could for example make abilities scriptable objects and allow designers to "drag & drop" them onto actors.
So no Inheritance; So the tower is just that; a class "Tower", that decides what to do with whatever "abilities" it is given
well... you probably will end up with an abstract base class for your abilities that does provide an abstract method like "ExecuteAbility"... and some abiliy execution housekeeping... but certainly dont inherit non-abstract classes or inherit multiple times without extremely well argued reasons π
and I'd probably end up with configurable but 'generic' (not in the code meaning) abilities;
e.g. Projectile and the a field 'effect' set as 'knockback', rather than "TornadoProjectile"
Would ExecuteAbility(), have Tower as their parameter, and let that do whatever it wants?
Yup.. I thought about it but then I'd need to pay even more attention to my details and formatting and nonsense.. and .. I unfortunately just don't have the time or inclination or channel to publish something like that to. π¦
could have something like:
public abstract class TowerBase: Monobehaviior {
public abstract int GetAttackDamage();
public abstract Sprite LoadTowerSprite();
}```
Then do something like
```cs
TowerLevelOne : TowerBase {
public override int GetAttackDamage()
{
return 20;
}
public override Sprite LoadTowerSprite()
{
return (sprite path)
}
}```
I'm hoping that at least, the general concept of splitting out some libraries isn't too specific (although I do recognize that a number of my implementation issues are)
I know I shouldn't over do the architecting ( but I must admit I like doing it - sometimes thinking about developing a game can be more fun then starting it :P )
i'd start with a prototype, where there is a Tower class which has a Method "TakeDamage" and in Update that tower randomly picks one of its N abilities which are scriptable objects and then it calls Execute(owner, targets) on the selected ability.
just to get started... then learn from what i dont like about that primitive version
Can you say- Would you do it like this: Where the ExecuteAbility() has reference to the tower; because with this I am unsure how I'd do "Projectile"
and rewrite the whole thing
i'd pass the context to the ability-SO, kinda like an event
I'll also have to figure out how this interacts with upgrades and the like...
always have data flow in one direction only, from the more general/bigger to the more concrete/smaller thing
I don't really want to have scriptable objects for upgrades and abilities
going to end up with very bloated folders
you can't avoid complexity, you can only hide it
There is a problem with that though,
Let's say:
My tower attacks whatever is at the lead in the enemy's path;
It has the "Projectile" ability:
How does the tower know it's meant to alert this specific ability? And then does that ability tell the tower to play an animation; no it cannot because multiple towers might shoot the same projectile
Perhaps every ability has a bool ShouldBeExecuted(LoadsofContext)
still not sure how to handle animation and all that shizzle
Also I'm wondering how tower defense towers decide on
- What is the "first enemy" in "my range"
without horribly looping over every single enemy on the track
the ability gets the context, who is sending it (which tower) and a reference to all enemies... or you handle context through triggers/collisions
The ability gets the context every frame?
So ExecuteAbility() is called every frame; and it decides if it just wants to break out or not
no, only when it is activated... it then does its thing (instantiate the effect)
depends on your game
See, with that; I'm unsure how I know when to activate it
because different abilities are bound to have different activation
I'm coming to the convo late, @queen plover , but one thing you could do is... when it's appropriate, check for the upgrade with a switch on the type pattern
Lemme dig up a code sample
Perhaps I ought to predefine animations too;
Force tower upgrades to have
"Idle Anim"
"Attack Anim"
"Special1 Anim"
"Special2 Anim"
and keep it strict to that
public abstract class PlayerAction {}
public class PlayerActionConcedeGame : PlayerAction {}
... etc ...
... then later when you need to dispatch an action based on the type ...
foreach (PlayerAction pa in playerActions)
{
switch (pa)
{
case PlayerActionConcedeGame _:
break;
case PlayerActionFieldMove paFieldMove:
break;
case PlayerActionGridMove paGridMove:
break;
case PlayerActionSkipTurn _:
break;
case PlayerActionUseActiveAbility paUseActiveAbility:
break;
default:
throw new NotImplementedException();
}
}
and then abilities can just decide if they use those animations
(if it's a tower "ability" anyway, that works)
if it's an upgrade, then you just ... check for the upgrade when you "consume" or "calculate" the value
Like, if you're calculating the max HP of the tower and the tower has an upgrade, you could instantiate the tower and check for that specific upgrade when you instantiate it (and maybe the upgrade has details about the % of HP increase, or whatever)
Yeah I just felt like I ought to avoid explicitly saying "If Ability is ProjectileAbility", because that violates SOLID, since Tower shouldn't have to be modified for me to add more abilities
public abstract class TowerUpgrade {}
public class TowerHPUpgrade : TowerUpgrade
{
public int PercentUpgrade {get; set;} = 0;
}
pseudo (inefficient):
Update() {
var readyAbilities = abilies.Where(it => it.IsReady).ToList()
if (readyAbilities.Count > 0)
abilities[Random.Range(0, readyAbilities.Count)].Execute(context)
}
It's probably be IsReady(Context) too
You don't have to modify tower to add abilities - you just make sure you "fall through" properly on your "if ability is __" if statements, buuuuuuut, it's not broaching SOLID because tower has to know about abilities/upgrades - they don't make sense outside of the concept of a tower, i think
was thinking about a simple cooldown....but yes, range checks and such
I can kinda visualize what I'll try and do
I would suggest that your tower provides the only public interface to values like "cooldown" or "hitpoints" or whatever, and put the domain logic for upgrades there (and literally no where else)
Still need to go more indepth into how I'll factor upgrades into this; but I'll figure that out on my own.
Any Insight on this though? ^
It's alright if not; It's a bit outside what I'm already asking
but I feel like it'd be good to know; because I reckon I'll make the enemy system before the tower one
Looping over every enemy is fine, although you could likely "denormalize" it by having a location manager subscribe to all enemies locations, and any time they move, it updates their location in some sort of custom data structure
It gets bad when Looping over every enemy contains distance checks as well though
ie - a zone, or a hard coded integer "path" Id - then your towers on that path only check the enemies on that Id
I'm not sure how else I'd check if it's in range
I suspect that it's probably not that bad - if it is, check for enemies in range less often - or perhaps have a tower "lock on" to an enemy and only find a new enemy when the current one is dead or out of range
how many enemies are you planning?
I'd probably do it with the "locking on" approach
I'll see if I have performance problems when I do it
I don't want to do the locking on approach, because I want to give specific targetting options
makes for a better gameplay experience i think - it might suck to have your towers just spraying bullets everywhere instead of focus-firing down a single enemy in range? i dunno
So you don't have to do that calculation every frame - only every time the tower needs to fire
you can always compare distances with Vector.SqrMagnitude(from - to) < weaponRange * weaponRange ... that is very efficient
I'll try have the "Path" class or whatever try and collect as much info as it can to cut down on how much stuff is happening for every single tower
and you certainly don't want to check for the tower needing to fire in Update().. i would do it with callbacks/events, if you're comfortable with that
though I reckon "First/Last in My range" could be tricky; I suppose I'll find out
It's maybe a bit more fragile then simply looping over all your towers every update() and seeing if they're ready to fire, and if so, firing.. but it'd be much much more optimized out of the gate
or just add trigger-colliders to everything and have unity physics do the optimized range checking
Is it possible for you to give me a example on how you'd do that; just a small description? Would the callback be everytime an enemy moves? because that's end up being every update
no - probably an event when you start firing and end firing that you consume internally, along with a public call to "check for enemy"
so.. something like this:
some boilerplate for you:
public bool IsFiring = false;
public IEnumerator FireBullet()
{
// find the nearest enemy, if any. If we found one..
isFiring = true;
// else return
// instantiate a bullet
// animate it toward the enemy
// calculate and apply the damage
}
public void StartFiring() { // start coroutine firebullet
}
... and then in some sort of TowerManager ...
public void Update() {
// if TimeSpan last checked towers to fire is > 1 second or something reasonable
// loop over all towers that aren't .IsFiring and .StartFiring()
}
that's .. really hacked together but hopefully you get the general idea?
i'd recommend starting with a very simple polling approach and optimize towards events when needed
basically you have some manager that literally just loops over all the towers once per second or two (maybe not even that often? play with it - should be a very very lightweight call) and then your FireBullet just restarts itself when it finishes firing
there's a lotta different ways to skin this cat, tbh
so I'm still having some issues with the tile not detecting if up and down are tiles
https://hastebin.com/ihiwinifim.csharp
on lines 73-77
it detects if theres one up or down
I think I generally err towards "premature optimization is the root of all evil" (google that) but in this case, it does sound reasonable that "every tower checking the distance to every enemy every frame" is going to be way too much calculation
but not if there's both
@queen plover (I forgot to include a call to "firebullet" at the end of firebullet, as well - it should just run continuously as long as there's a target in range)
depends on the number of actors i guess
for sure.. i actually think that this approach (every tower check every enemy every frame) is probably still fine for 20+ towers and 20+ enemies? sorta just guessing
and can be very quick to do if they update their own position inside a spatial index (quad-tree, BVH, ...)
this approach also allows you to have weapons that are like "lasers" that apply damage every tick, rather than having discrete bullets
the laser just automatically switches targets whenever one is in range, and applies damage uniformly and instantly to anything in range.. which is kinda cool
i.e. instead of comparing vs. all actor positions, just have the tower query "who is in this box"... and check distances only for actors in the box
well, i mean, that's still the same calculation, no?
I plan for the enemy count to be quite high, and tower count is practically up to the player (it's going to be freeform placement)
oh i see what you're saying
Optimization will be needed- but I won't do it too much prematurely
sure but "practically up to the player" is still bounded by you - is it 10-100? 1000-2000? π
i like this approach now that i think about it
(at least for the "findClosestTarget()" method)
trigger colliders do that automatically and very efficient... just need to make sure the collision matrix is set up right
private Vector2 topLeftOfRange = ...;
private Vector2 bottomRightOfRange = ...; // or use a rect2d, whatever
...
private Enemy GetClosestEnemyInRange()
{
List<Enemy> enemiesToCheck = BattlefieldManager.GetEnemiesIn(topLeftOfRange, bottomRightOfRange); //foreach all enemies, check their position - no distance check required
foreach (Enemy e in enemiesToCheck)
{
... find the closest ...
}
return closestEnemy;
}
or yeah, colliders
I'm going to head to bed now- @misty glade @compact ingot @regal olive Thank you very much for all the Info <3
goodnight, i still have my bugs to fix lol
GN - don't forget to wake up in the middle of the night and jot down your solution
π
In a cold sweat after a nightmare about trying to figure out how to optimize things of course
but then I forget the solution before i can find a pen and paper :P
I'm still trying to figure out why my tiles detect if there's an up or down tile but not both
@regal olive I tried to find the original code/question - I'm piqued, could you restate the problem and paste your code again..?
yeah let me just edit it a bit
private void Update()
{
var renderer = GetComponent<SpriteRenderer>();
if ((down != null && down.TryGetComponent(out TileWall twww)) && (up != null && up.TryGetComponent(out TileWall twwww)))
{
Debug.Log("DOWN and UP are Walls");
renderer.sprite = Resources.Load<Sprite>("WallTopBottomConnected");
}
if (up != null && up.TryGetComponent(out TileWall tw))
{
Debug.Log("UP is Wall");
renderer.sprite = Resources.Load<Sprite>("WallTopConnected");
Debug.Log("UP is Wall 2");
}
else if (down != null && down.TryGetComponent(out TileWall tww))
{
Debug.Log("DOWN is Wall");
renderer.sprite = Resources.Load<Sprite>("WallBottomConnected");
Debug.Log("DOWN is Wall 2");
}
}```
1 = first tile placed, 2 = 2nd, etc
once I placed down 1, it has the unconnected texture. Then I placed down 2 on top of it, then 1 changes to topconnected but 2 does not change to bottom connected
basically the previoustile placed isn't updating all the time
(separate issue.. you shouldn't be doing a Resources.Load() in Update())
yeah, i'm digesting.. standby π
okie
where/when/how do you set "down" and "up"?
(you also don't want to GetComponent() every update.. that's gonna bring your app to a crawl real quick)
private void Awake()
{
GridManager GM;
GM = GameObject.Find("GridManager").GetComponent<GridManager>();
//Start detecting neighbors
thisPosition = GM.tiles[Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().x), Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().y)];
up = GM.tiles[Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().x), Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().y + 1)];
down = GM.tiles[Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().x), Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().y - 1)];
left = GM.tiles[Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().x - 1), Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().y)];
right = GM.tiles[Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().x + 1), Mathf.FloorToInt(gameObject.GetComponent<TileBase>().GetGridPosition().y)];
}```
in awake I set up down left right
since that's the immediate frame when the tile spawns
k
and you're sure that's working? and not giving you the wrong floor when you're around 0
cuz remember floor of -0.5 is 0, but so is 0.5
k - i might also make this a bit easier to read by not calling the GetGridPosition 10 times when you need to once -
yeah lol
before this I didn't have getgridposition
so it was a thousand times worse
using static Unity.whatever.Mathf;
private void Awake()
{
GridManager GM;
GM = GameObject.Find("GridManager").GetComponent<GridManager>();
Vector thisLocation = gameObject.GetComponent<TileBase>().GetGridPosition();
//Start detecting neighbors
thisPosition = GM.tiles[FloorToInt(thisLocation.x), FloorToInt(thisLocation.y)];
/// ..etc ...
}
if (up != null && up.TryGetComponent(out TileWall tw)) // shouldn't this be else if?
I honestly suspect that your Awake() logic is what's broken - I would probably add something just to verify that down isn't null when you place 2
aren't you getting array out of bounds errors whenever you place down a tile?
unless you wrote a custom indexer for the .tiles member of GridManager?
show me your definition of GameManager.tiles
I'm not no
lemme show the whole script
its apart of an abstract class
I wanted to see GridManager - can you hatebin that?
yeah
So also, while I was looking here.. I don't think these tiles need to be subclassed.. they just look like variations on a tile?
(with hard coded properties..?)
anyway, different thing.. stay on target @misty glade :p
Well it's an easy way for me to code in tiles with different properties
oh duh
you're setting down/up/right/left in Awake and never again
so obviously once you place a tile down, the existing tiles aren't going to magically get new down/up/right/left values
oh
your code is already going to suffer from optimization issues with your update function but you can worry about those later π
do this instead:
there's probably a simpler way to do a texture update system
public void CalculateNeighbors()
{
//... your code that's in awake that figures out up/down/right/left
}
public void Awake()
{
CalculateNeighbors();
GM.RecalculateAllTiles();
}
... then in GridManager ...
public void RecalculateAllTiles()
{
// for each tile in tiles
// {
tile.CalculateNeighbor();
// }
}
also you should move all that texture setting and stuff to CalculateNeighbors(), realistically, so it only happens when the user places a new tile, not each and every frame
I did have something similar to this, I was just putting it in update instead of awake. hmm
Resources.Load() is something you want to call as few times as possible
the issue is that I can't use the inspector for this script
well you have logic in awake that is figuring out who it's neighbors are, but once a tile goes down, awake never gets called again (so a tile will never get "new" neighbors)
you could use the inspector for this script but that requires a bit of work
you'd want some sort of field that makes sense in the inspector for an object
or alternatively you could rename your instantiated prefabs to their grid location or something else
Anyway, hope that helps.. gonna get back to my work :]
I'll let you know if it did! Thank you for ur help π
Sorry to bother you, but I'm having some trouble trying to do tile.CalculateNeighbor()
I have:
public void RecalculateAllTiles()
{
for (int i = 0; i < Columns; i++)
{
for (int j = 0; j < Rows; j++)
{
tiles[i, j].GetComponent<TileWall>().CalculateNeighbors();
}
}
}```
For that
I'm getting a nullreferenceexception on tiles[i, j].GetComponent<TileWall>().CalculateNeighbors();
Either tiles is null, or the element at tiles[i,j] is null, or it doesn't have a TileWall component attached to it
figure out which one and why
Adding log messages is a good way to figure out which.
Also this is kind of a #π»βcode-beginner question tbh
once it loads back up ill check on it
advanced isnt really defined anywhere here
meaning of advanced is pretty much straightforward. you'd find more and quicker help in #π»βcode-beginner is what he meant to convey
He's not wrong, unfortunately - how to check for null and how to write code that doesn't expose NRE's is generally a beginner topic. In any case, you are likely calling Recalc in your Awake() method in GridManager, but you're not initializing the array until your Start() method (unless you changed it from before)
Awake() comes before Start()
and also you shouldn't @ someone for an answer.. one of the mods might pull out the spanking stick π
What would be the best way to write a snapshot of the current scene into a byte array so it can be sent to clients?
can you rephrase that?
Pretty sure you don't, there's no way to restore scene state like that
Does anyone know how to save tilemap data to files?
the best way is to distill the data down into the minimum amount of information the client needs to recreate the scene locally for itself, serialize it, and send that
There aren't really any shortcuts for this
Okay honestly reading what you wrote that was not clear at all
The way to cut a wedge in half is, you make a prefab with the wedge and its halves, and you toggle between them
It seems simple so I must be missing something
How would you folks go about implementing a Status Effect system? Scriptable Objects? Inheritance? Etc?
I'm trying to figure out the best way to actually handle all of this.
all of the above maybe?
Maybe. Lol
probably make a base class for a StatusEffect that has some common methods on it that let you process them all generically each turn (does your game have turns?) e.g.
void OnTurnPassed()
void OnEffectAdded()
void OnEffectExpired()
void OnEffectRemoved()
then have a list of effects for the character and something that processes adding them, removing them, and processing them each turn?
and have each effect class implement those methods?
Β―_(γ)_/Β―
Yeah, I'm really not sure?
I'm fairly sure Interfaces are the best way forward, I'm just not entirely sure how to handle update ticks on it etc.
you need some kind of orchestrator object that loops through all the active status effects and calls a Tick() method on them
Yeah, also what I was thinking.
I have a web-gl game (uploaded to itch io). I want the user to copy the string from the game. One approach that I know is to have Unity call a javascript function (a popup box) and pass the string to the popup box (mentioned here: https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html). I see that I'm able to pass the string but the user still isn't able to copy the string from the popup box. Any ideas how to do this?
i have an abstract class, in it an abstract Execute() method. I have different classes that inherit that class and does different things. i want to be able to save a list of those classes as json, then after load it, and be able to call that Execute() method. i tried saving the class name and assembly in the json file, then load it using Activator.CreateInstance(), but it seems to crash unity. Having a switch statement for each class works but id rather a better practice. Im doing this in the goal of game modding. Does anyone have any ideas on the best practice to achieve this?
does your abstract class inherit from MonoBehaviour?
no it doesnt
CreateInstance should work, then. Do your constructors have any arguments?
one hang up I've come across is that it doesn't implicitly convert arguments well, so make sure they match exactly
constructors for the abstract class? there are none in it.
the derived classes
they dont have any either
are there any clues in the logs or crash message, then? Your approach should work
it isnt so much of a crash as more of a freeze. theres no clues i can find.
im glad to hear im on the right track at least π
hm, i wonder if im just using CreateInstance wrong?
NodeInstance is my abstract class, and the error isnt shown
if(type != null)
instance = Activator.CreateInstance(type) as NodeInstance;
else
UnityEngine.Debug.LogError("GetType() returns null: " + nodeName);```
OnStart is the name of the class? Does instance = Activator.CreateInstance(typeof(OnStart)) as NodeInstance; cause a similar issue?
OnStart inherits the abstract NodeInstance yes. sorry, should have mentioned.
i switched that line, and unity is frozen now. it appears so
Is OnStart itself also abstract? Does it implement all abstract methods?
its not abstract itself, and it implements all methods
unfortunately i have to leave for work, thanks for the help so far, ill be back
try:
instance = new OnStart() as NodeInstance; and if that works, then
instance = Activator.CreateInstance(typeof(OnStart), null) as NodeInstance; next
ill try once i get home, sorry to cut off like this π
np, maybe someone else will see in the meantime and you'll have your answer when you get back
Is it possible to set UnityEvent to invoke a function from a script, using the inspector?
yes
I can't see the option. I tried using a c# standard class, a monobehaviour and a component with the same monobehaviour, and none allowed to invoke a function from the class
you have to pick the gameobject in the editor and then you can view the methods on it
is the method public?
Sorry.
anyone got idea what the hell is happening, stuff disappear from the game and when i check the scene everything is there
Sorting layers?
{
var ray = new Ray(Origin, direction);
var currentMinDistance = float.MaxValue;
var hitPoint = Vector3.zero;
var planes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
for (var i = 0; i < planes.Length; i++)
{
// Raycast against the plane
if (planes[i].Raycast(ray, out var distance))
{
// Since a plane is mathematical infinite
// what you would want is the one that hits with the shortest ray distance
if (distance < currentMinDistance)
{
hitPoint = ray.GetPoint(distance);
currentMinDistance = distance;
}
}
}
// Now the hitPoint should contain the point where your ray hits the screen frustrum/"border"
lineRenderer.SetPosition(0, Origin);
lineRenderer.SetPosition(1, hitPoint);
} ```
for some reason i get hit only on left and down the right and top being ignored any idea?
maybe bc planes are one-sided so the ray is going through the back side of the plane?
you could try rotating the planes to fix that
yup that looks like it could be the issue so did you try rotating those two planes?
no i didn't at what axis should i rotate and at what degree sorry i have no idea
i think the calculated Frustum Planes can't be rotated !
I don't think that would be the problem but to rotate the plane you'd just do plane.Flip();
i tried flip there is no difference even with the working one (right,down)
is your camera orthographic? does your direction lie on the plane defined by the camera forward dir? And finally, I assume you only are interested in the four edges and not the near and far plane, so test the first four planes and ignore the last two in your loop
it is perspective
Yeah I wouldn't think that flipping would make a difference
does your direction lie on the plane defined by the camera forward dir? i didn't understand that part
Based on the video you have some weirdness with the direction?
It seems like it's not always following the joystick
like Praetor said, your direction looks wonky to me. So I wanted to eliminate any cases where your direction is pointing in a way that is either wrong or hitting something early (i.e., the near plane might be the nearest intersection)
it happen only when there is no hit and that happen with top and right only .... the line should be start drawing from origin which is the stick holder to the direction which is the hit point
ah yeah ignoring the near/far planes would be a good idea
i did that there is no difference
can you show your code for deciding the ray direction?
yes sure
Vector3 direction = MousePos - StickParent.position;
GetHitPoint(StickParent.position, direction);```
StickParent is just the stick holder
Ok so it seems like
you've got mousepos that is in screen spacew
What is StickParent? Is it a UI element?
yes it is UI
right so
the planes you get
are in world space
and everything here is in screen space Vector3 direction = MousePos - StickParent.position;
so you've got a ray in screen space and you're trying to use it against planes in world space
that might be part of your issue
any idea how to convert those planes to screen space !
i guess i don't need CalculateFrustumPlanes since am in screen space
this channel feels new π€
@long ivy idk what the issue was, but after changing some code around it works now. i wonder if there was an infinite loop or something dumb, but either way i appreciate your time and help! thanks!
in Unity, is it possible to have built project and then work on scenes as levels in other project? And then open those levels in built project. I want to find a level designer, but I don't want to share the whole project right away. First to try what could he do.
Sure he can export his scene as a unity package and you can import it
You can export a base package as well to have him work with the right tools and settings
Not advanced code btw
So he will be able to test level by himself, right? Like export it as package and launch in the built project?
Oh the build no sorry I didnt get that. No a unity pacakage will not work in the build. He will send you the package and you put it in your editor. For him to insert custom assets into a build you have to basicly do mod support
Look into asset bundles and adresabbles etc
Thanks! Will check it out.
The assets not custom. There are some prefabs he'd have to put on stage. Like where the player spawned.
Just the gameplay script, UI and all that stuff would be taken out. Just in case so he could not give away the source of the game. Cuz I'd probably deal with a dozen or even more people about level design role.
You can make them sign a document called a NDA then you have some legal action :)
I would like to start splitting my game's processes to multiple threads
how could I move pathfinding for the nav mesh agents to other threads?
hey. I wanna make two animations play alongside. each animation controls one child. the prefab is like so :
root
- child A
- subchild A
these are not RIGS.
any way to do that ?
that the anim1 controls child A and anim2 controls subchild A. now the desired result would be that when anim1 moves, it should move subchild A as well, like parent-child relation transform, nothing special. but also the subchild A has to move based on anim2 too. relative
it would need something called Mask in Unity. i know that
but this parent-child relations aren't rigs . they're simply some GameObjects. so I can't use the built-in mask
Do you mean two separate animators?
two seperate masks
This not a programming question, but you use layers in the animator.
Each layer has a separate mask
Then you set the same condition for each to start
that doesnt work. to my surprize , animations dont only control the nodes we give them they control the *all childs and just put a zero in their change values. so this solution isnt working without masks
If the animations do not affect the same objects you will not need a mask, just make sure that each does not control the same property on the same objecct
Manually delete the curves that do nothing from the animations
Then they'll work independently
btw there's no animator group to ask it , so i guessed since it's advanced, i might come here to ask ^ ^
#π»βunity-talk is the place for this one
Oh wait, no
But not any of the programming channels, unless you want to talk about the animator API itself
not an option. as i said. animations change everything . it's their way. not customiazble. the mask is for limiting them
I happen to know that you're incorrect.
Animations do not change everything, only the properties included in their curves
I know this because I recently went through this process myself.
thats art channel tho...
look. I'll make a new project for testing this and then i'll record it so u can see it more clearly
Share it in #πβanimation, you can @ me but I'll likely be asleep
oh , forgot the timezone thing. sorry for bothering u at night then. yeah sure i'll continue in there.
can someone help me with serialization?
I wanna be able to save a binary file that contains stuff like items, profile names so I can identify the saves
https://youtu.be/XOjd_qU2Ido
make a custom class to store data, mark it as serializable, use the unity stream to read/write, and have methods to convert between the data class and the actual class
Here's everything you need to know about saving game data in Unity!
βΊ Go to https://expressvpn.com/brackeys , to take back your Internet
privacy TODAY and find out how you can get 3 months free.
β Easy Save: https://bit.ly/2BzgdXb
β₯ Support Brackeys on Patreon: http://patreon.com/brackeys/
Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·...
I've used this exact system and I struggle to understand it really
I wanna save stuff that's not just in one script so I'm kinda struggling
And I'm also very tired nowadays so, that's that
You might find it easier to use JsonUtility
If you just want to get it working
And come back to binary later
The save system doesn't really need to be on an object, I tend to use a static class for it
I have an inventory script that holds a list of a class I made in it
That class has a scriptable object, an int and a scene (which I can just change to a string if I need to)
And I also wanna save position
Idk how to save from multiple scripts
I am
Just
Confusion
just look into saving in Binary, it's the quickest way of saving / loading data
Atm, I have a script that's on the player that other scripts on it can reference
From that script I call the save and load functions
It does change the file size, but still gives me an error
And fails to read and load data from it
and avoid Brackeys when it comes to stuff like this, the info they give is generally outdated.
I am using a different method to dave and load
Using a try get function
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
public class SerializationManager
{
public static void SavePlayerData(PlayerData playerData)
{
BinaryFormatter formatter = GetBinaryFormatter();
if (!Directory.Exists( Application.persistentDataPath + "/saves/"))
{
Directory.CreateDirectory( Application.persistentDataPath + "/saves/");
}
string path = Application.persistentDataPath + "/saves/" + playerData.profileName + ".save";
FileStream fileStream = File.Create(path);
formatter.Serialize(fileStream, playerData);
fileStream.Close();
}
public static PlayerSaveData LoadPlayerData(string profileName)
{
string path = Application.persistentDataPath + "/saves/" + profileName + ".save";
if (!File.Exists(path))
{
Debug.Log("No profile data saved.");
return null;
}
BinaryFormatter formatter = GetBinaryFormatter();
FileStream fileStream = File.Open(path, FileMode.Open);
try
{
PlayerSaveData playerSaveData = (PlayerSaveData)formatter.Deserialize(fileStream);
fileStream.Close();
return playerSaveData;
}
catch
{
Debug.LogErrorFormat("Failed to load file at {0}", path);
fileStream.Close();
return null;
}
}
public static BinaryFormatter GetBinaryFormatter()
{
BinaryFormatter formatter = new BinaryFormatter();
return formatter;
}
}
here's the saving code
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
[System.Serializable]
public class PlayerSaveData
{
public string profileName;
public Scene scenePlayerWasIn;
public float[] position;
public float[] rotation;
public Inventory inventory;
public PlayerSaveData(PlayerData playerData)
{
profileName = playerData.profileName;
scenePlayerWasIn = SceneManager.GetSceneByName(playerData.scenePlayerWasIn);
inventory.itemList = playerData.itemList;
position = new float[3];
position[0] = playerData.transform.position.x;
position[1] = playerData.transform.position.y;
position[2] = playerData.transform.position.z;
rotation = new float[3];
rotation[0] = playerData.transform.rotation.x;
rotation[1] = playerData.transform.rotation.y;
rotation[2] = playerData.transform.rotation.z;
}
}
and the serializable script I made
can I serialize scenes?
If you wanted to, sure
for performance reasons, I would use an Index, strings are unperformant
I know
Well, declare a List in the serialisable class
but I change them a lot
and it really doesn't matter all that much
I change the scenes a lot and it's impossible to work with ints
the index isn't gonna be the right one
or?
it's not gonna be the same then!
also
public class ItemSlot
{
public Item item;
public int amount;
public Scene scene;
}```
I wanna save a list of this
can I just directly do that?
complicated saving system
if a player joins another player's world with items from a region that hasn't been unlocked in that world
then I can use that variable to remove them from their inventory
or just
hide them
Oh I see, it's multiplayer
yes
SerializationException Type 'UnityEngine.MonoBehaviour'
fricc
I really don't understand much of this
can we start from like the basics
the start I mean
One of the things you're trying to serialise appears to be derived from MonoBehaviour
yeah, but what
I'm not sure, I'm not you
Ah, you should probably use that other class you made
the player save data
I see
and from the monobehaviour one I can call this
omfg it works
scriptableobject is not marked as serializable
nice
i don't think you'd want to save an SO
hello i am using perlin noise to generate dungeons but the output is repetitive. Is there a way to go about infinitely procedurally generated dungeons without repetition
perlin function output has so little. with a float input between 0 and 1, also after 4 digits its irrelevant so its just like 10,000 blocks of generation, after that it repeats
nvm it's not working-
well
what else can I do then?
that's how the items are made
I found a solution of making a class for each item and then referencing it in the scriptable object class
but idk
didn't work-
:/
if it's loading from save then you can spawn the items from the class itself
and if it's not then use the SO
wdym?
when you create an item, pass in the data class for the item that you got from the save
instead of a scriptable object
yes but I failed doing that
I'll try later idk
thanks anyways! at least now I know how this works!
I am trying to make 2d, tile based line of sight/fog of war visibility thing
But I run into these issues when casting my "shadows" from nearby walls
Anyone got solutions?
this is the raycasting function
Your dx/dy should be floats, then round them to int to check the cell
Otherwise you'll only be able to step on diagonals or straight
thats how DDA works
@lavish epoch https://www.reddit.com/r/roguelikedev/comments/358mt5/faq_friday_12_field_of_vision?sort=top
Roguelike tutorials will cover this exact thing perfectly
This exact FOV is in nearly every roguelike
really? I didnt find any information on this at all
can you link a tutorial that does this?
There are a few approaches here
Looks like the most robust is to cast to every square in range
But if the range is small enough you can just trace the boundary
I am casting to every wall in range, then casting again from that wall to further away to put shadows
forget the 1st part of my sentence
I can afford to make walls cast shadows even if the walls themselves arent visible
Right. Well usually shadows are an absence of light
So I've done this in euclidean space
in this case shadows are 1x1 squares that block view