#archived-code-general
1 messages ยท Page 146 of 1
The big issue I have with your current implementation is that is not enough flexible, i.e. robust to change. Your save game should not know what a player is. It violates the principle of Tell don't Ask.
If you stay like that, your game is going to be non flexible and it will be hard to keep adding new object. Instead, you should consider using an approach with interface such as:
public interface ISaveable {
public object Save();
public void Load(object data);
}
public class Player : ISaveable
{
public class SaveData {
public int Level;
}
public object Save()
{
return (object)new SaveData();
}
public void Load(object data)
{
}
}
public class SaveManager {
public List<ISaveable> saveables = new List<ISaveable>();
public void Save()
{
foreach(ISaveable saveable in saveables)
{
//Do Save
}
}
}
Yeah this is a similar approach I used in my past game, but I found it got pretty cluttered implementing the interface throughout all the scripts.
This is way better than what you are suggesting.
- It reduce the coupling between your SaveManager and the different Object.
- It increase the locality of change whenever you add new element in your save.
- It prevents your implementation from leaking out of your class. (Encapsulation)
Yeah, I do think it's better, I just didn't enjoy it lol.
Might try another variation of it though.
What did you not enjoy ?
.
What exactly was irritating with the interface ?
The fact that it added codes to your class ?
Sort of, more so that it added code to many classes, and many classes had to be updated throughout the project when new things were added, rather than one central location.
What do you mean by many class had to be updated ? Because it usually is the opposite.
If you add a new class, there is no need to make any change exept to this specific class.
I'm asking those question because interface is not the only way of having this seperation.
I mean the implementation of the interface for each class that needed to be saved, had different implementations. I'm trying to look through some of the classes I had let me see... this was like 9 months+ ago
It is kinda normal to have different implementation depending on the class though.
Some were very covoluted such as:
public void LoadData(GameData data)
{
if (data.serializeableFishCollected.TryGetValue(nameOfFishHeldWithinSlot, out FishStats fish))
{
if (fish.numOfFishCaught > 0)
{
fishTextCount.text = $"Amount Caught: {fish.numOfFishCaught}";
fishTextName.text = nameOfFishHeldWithinSlot;
fishDescription.text = fish.descriptionOfFish;
instanceOfSilhouette.SetFloat("_Hide", 0);
SetFishLengthSliderOnLoad(fish);
PopulateFishCollectionDictionaryUponLoad(fish);
}
}
}
public void SaveData(GameData data)
{
foreach (var kvp in fishCollected)
{
if (!data.serializeableFishCollected.ContainsKey(kvp.Key))
data.serializeableFishCollected.Add(kvp.Key, kvp.Value);
else
data.serializeableFishCollected[kvp.Key] = kvp.Value;
}
}
Others were of course much simpler:
public void LoadData(GameData data) => transform.position = data.playerPosition;
public void SaveData(GameData data) => data.playerPosition = transform.position;
if you make a System Serializable data container class, create a set of values, and then assign them to a public reference, what happens to the inspector values?
And then I still had my one GameData class:
[System.Serializable]
public class GameData
{
public int playerMoney;
public Vector3 playerPosition;
public bool wasBasicFishingPoleBought;
public int wormCount;
public int progressBarValue;
public SerializableDictionary<string, FishStats> serializeableFishCollected;
public bool hasBasicFishingPoleTipBeenDisplayed;
public bool hasWormTipBeenDisplayed;
// Default values when starting a New Game go in this constructor.
public GameData()
{
wormCount = 0;
progressBarValue = 0;
playerMoney = 35;
playerPosition = new Vector3(18.23f, 1.997f, 76.922f);
wasBasicFishingPoleBought = false;
serializeableFishCollected = new SerializableDictionary<string, FishStats>();
hasBasicFishingPoleTipBeenDisplayed = false;
hasWormTipBeenDisplayed = false;
}
}
Oh, the issue is that you are reusing the same class through all save.
I just felt like it get so messy overtime
This is not what you should do.
You should have 1 class per object.
You understand the difference between what I am suggesting and what you have done ?
Not yet ๐ but i'm listening...
You have 1 class containing the whole save data.
I have several class containing the data.
The result would be:
{
"0000-0000-0000-0000" : {
"Level": 0,
},
"0000-0000-0000-0001":{
"HP" : 0,
}
}
You would define an object that holds the data per class.
hmm ok this structure makes sense.
There is also other method that reduce the amount of boilerplate needed.
Such as reflection and code generation.
You can also use partial class if you dislike having the save code in the same class as your main class,
However, I think using #region is more appropriate.
Thanks, I'm going to mess around with what you have here and ensure I understand it.
So I'm messing around with some solutions to particle systems vs floating origin and found something really odd...
I made a "parent" transform to put all the particles in called "ParticleSpace" this lets me pick up all the existing particles at once and move them 1 "stage size" over along with player, camera and all game objects, whenever player and camera get too far from origin
problem with that method is the transform of the particlespace will drift from origin, so to test it out, I put it 10 million units away... so particlespace origin is at massive negative x but particles are generated at massive positive x in local coords within that... what's weird is it didnt lose positional accuracy so much - but it lost the ability to rotate particles
they all generate at the same angle... very odd IMO
A reference? Do you mean an instance of the data container? Do you mean if you assign values to the variable in the class? If so, the inspector will show the new values assigned to them (not sure if I fully understand your statement though) . . .
Actually, think I got it... messing with it more still.
this is shader related but the snag I'm hitting is on the code side.
I am trying to encode barycentric coordinates into vertex colors. I found a component online in github, but theirs only draws a wireframe of triangles, I want to draw a wireframe of quads. I found a vert/frag shader that correctly draws quads as well, but I have been trying for hours to marry the logic from the quad into the logic that encodes vertex colors but to no avail
their code is so efficient that I am struggling to understand what it is doing and how it works, they make so many lists and sublists and call things labels and just the logic is all over the place in ways that are extremely efficient, but also completely opaque
I've tried to parse it repeatedly, and you can see in the 'encode' file there's 3-4 attempts I've made to re-write/recreate what they're doing from scratch, written in a way I understand, but none of my attempts produce results like theirs
!code
๐ Large Code Blocks
Large code blocks should be posted as links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/
https://paste.myst.rs/, https://hastebin.com/
๐ Inline Code
Surround code with three backquotes. Not quotation marks.
To get C# formatting the first line should only contain cs or csharp.
Add a comment with a line number if there is an error message.
```cs
// Your code here
```
Do not share screenshots of code unless requested.
TLDR: I want to refactor this other person's code to support my use case of detecting the longest edge of each triangle and adjusting those values so that the end result shader culls those edges out, but I can't penetrade their hyper efficient logic to make those changes
[maxvertexcount(3)]
void geom(triangle v2f IN[3], inout TriangleStream<g2f> triStream) {
float edgeLengthX = length(IN[1].vertex - IN[2].vertex);
float edgeLengthY = length(IN[0].vertex - IN[2].vertex);
float edgeLengthZ = length(IN[0].vertex - IN[1].vertex);
float3 modifier = float3(0.0, 0.0, 0.0);
// We're fine using if statments it's a trivial function.
if ((edgeLengthX > edgeLengthY) && (edgeLengthX > edgeLengthZ)) {
modifier = float3(1.0, 0.0, 0.0);
}
else if ((edgeLengthY > edgeLengthX) && (edgeLengthY > edgeLengthZ)) {
modifier = float3(0.0, 1.0, 0.0);
}
else if ((edgeLengthZ > edgeLengthX) && (edgeLengthZ > edgeLengthY)) {
modifier = float3(0.0, 0.0, 1.0);
}
}```
This is how the shader expects the data to be formatted, the longest edge has more R, G, or B, but I haven't been able to bring that over to the other persons code
Like they're doing all kinds of sorting on the triangles for reasons I don't understand, but all my attempts to do this without sorting the triangles failed
but all their sorting and rearranging and labeling and indexing are making it beyond my ability to figure out when/where to do the checks for longest edge and add that resulting color
its midnight in my timezone so I am putting this to bed for the moment but I need to get this solved and I am beyond my ability to solve it myself
spent about 20 hours on this so far
Alright, I didn't understand this well enough. If you got some time to follow up with a more complete example, it would be appreciated!
I am working on a script that allows the player to buy healable objects. The problem is that when I try and add a key to purchase the item it does not go through but when I do not use an if statement and the player just collides with the object it just goes through immediately. This is my code -> https://hatebin.com/rwipcflzha. Any help is appreciated.
this might be weird but can someone hop in a vc with me and help me with my vr games
https://docs.unity3d.com/Manual/ExecutionOrder.html
Before the first frame update
Start: Start is called before the first frame update only if the script instance is enabled.
For objects that are part of a scene asset, the Start function is called on all scripts before Update, etc is called for any of them. Naturally, this cannot be enforced when you instantiate an object during gameplay.
Does this part in the docs mean that an object can run its update before running its own Start? Or does this line just mean that its possible a script runs its start after another script ran its update in the same frame?
if the GameObject exists in the scene, all scripts (on that GameObject) will run their Start before Update. if instantiating a GameObject, all its scripts may not run Start before Update is called on one โ or many โ of them . . .
basically, the latter of your response . . .
you need to move the input check in Update. this will "attempt" to check for input (E key) during the single frame the GameObject collides with this one . . .
Hey, I've written a simple tool that generates pose info for my hands by storing a List<Tuple<string,Vector3,Quaternion,Vector3>> in a ScriptableObject. It works correctly and can save the pose and load it on another hand until the original gameobject that holds the tool is destroyed, in which case the scriptable object is empty for some reason.
I write and save the info like so:
poseInfo.right = right;
if (AssetDatabase.LoadAssetAtPath(parentPath + poseInfo.name + ".asset", typeof(HandPoseInfo)) == null)
{
AssetDatabase.CreateAsset(poseInfo, parentPath + poseInfo.name + ".asset");
}
AssetDatabase.Refresh();
EditorUtility.SetDirty(poseInfo);
AssetDatabase.SaveAssets();```
I can gaurantee the left and right collections are populated, they only are emptied after the original object is destroyed. How do I go about saving a scriptableobject to the disk properly?
try replacing Tuple with custom serializable type
Ah, okay. Will try
unity wont serialize generics unless you use SerializeReference, it may not serialize tuple anyway
Yeah, I figured something like that might have been a worry but never though too much about it
Could I just use a struct?
What other type could it be?
Is a class not overkill for four values?
define overkill
Fair enough. I don't need methods or anything is why i figured
structs can have method
the limitation is that interface cast to object in some conditions
Oh
So literally just this is serializable?
Still not sure what the rules for serializable are
the only benefit you get by storing as a struct is that it will be embedded into the object, you skip one dereference
just add System.Serializable
and read docs on unity serializer its rules
That stuff is fine inside a struct ๐
why?
can you predict all the edge cases ahead?
There are no references inside that struct. Why would you waste heap allocations when you can just have it on the stack?
no references? string is a reference
True, to be fair
you cant predict all the edge cases that arise from copy semantics and designing your api from the get go with it
I'd also remove that
i mean, you can if you try hard, and you know exactly why you are using struct
and you understand all the implications, but if not the marginal nanoseconds you save can become a massive headache in the long run
What is "path" and why is it on "transform clone"?
Tool recursively stores transform scale, rotation, and position of each bone in a hand so it can be arbitrarily apploed to any other hand
does anyone know how to fix this
Make sure you're using HTTPS not HTTP
how do i change it
Instead of
http://google.com
Use
https://google.com
its SteamVR package throwing
oh
this isnt compiler error right? you are launching the game and you see this
do you have steamvr installed/steam running?
I booted up unity and that started happening
and i have like 999 errors
Yes, a class marked as serializable works properly now, thank you for the help .cache and Tom
okay im sorry
I dont have a SteamVR Folder
What's that screenshot meant to show
Based on the error, you definitely have the folder. You may want to stop filtering too.
it's in the middle of a search and shows nothing in Assets that's relevant
okay sorry
im trying to move an object in my scene but all of a sudden its not letting me drag it around
im selecting it in the scene but the arrows arent showing up
not sure why thats happening
i did that
something wonky is happening
not sure what i did
i can select the object, but it only highlights it with orange
and no move arrows appear
Try reopening the scene view and resetting your layout if that doesn't work (also this is not a coding question)
ah kk sorry
anyone know why I'd get UnauthorizedAccessException from system io filestream when I write to Application.persistentDataPath?
StreamWriter writer = new StreamWriter(Application.persistentDataPath);
foreach(RaceLogEntry entry in m_RaceLog)
{
writer.WriteLine(entry.position.ToString() + "," + entry.velocity.ToString());
}
writer.Flush();
writer.Close();
Application.persistentDataPath is a folder, how are you expecting to write to it
You need to create a file inside it.
is it better to use m_foo or foo in script where both field and property exist?
oops
C# Coding Conventions are pinned, private members are _privateMember
A property is written with a capital letter and a private field is written with a lowercase letter and an underscore
Don't look at Unity's syntax
I am talking about m_
I use it too
What is the simplest way to stop motion using raycasting?
They did it different because of reasons but it's really not used nowadays
What Vertx said, there are code conventions pinned
What does this mean and what does it have to do with code
private int m_textComponentIndex;
private int textComponentIndex
{
get => m_textComponentIndex;
set => SetTextComponentIndex(value, false);
}
I use it too
It seems nice
We know you use it, why though is a mystery
because it's readable
do you even know what m_ stands for
Nobody is going to slap you on the wrist for it if that's what you're expecting
You're not forced to do it
they use m_ for fields with properties and _ for private fields
Nope
I know what they do
yes
Why exactly are you asking these things if you're just going to argue?
I'm glad Unity decided to change to C# standards in most of their new packages
I have asked whether it's better to access m_foo or foo property within your own script
in most? is it used just in old?
There's no better, there's only conventions that you are recommended to do to keep in line with everyone else
If you want to prefix all your fields with m_, feel free to. It just doesn't make sense because that's not why they're prefixed like that
I see
thx for help
Good job team
Yes, it's not something Unity has done in most of their new packages. See Splines, Entities, etc. Cinemachine 2.0 has partially moved (only for the public members)
maybe that's because different programmers were writing those scripts
f_speed
s_name
I actually thought it represented the actual purpose, like m_ being for MonoBehaviour and such. Turns out it's old c++ conventions to indicate class member variables
thats a strange question, if you access int foo {get;set;} there is no difference because it will be inlined, but if you access the set of the property you posted vs the field the results are completely different, so the "whats better" doesnt make sense
yes, I know, foo just returns m_foo
what does m_ stand for?
"member"
and just _ ?
that's just for private fields
and private fields are?
not public
they arent members?
are
so if its for members that are private what else does m_ cover?
foo is for public variable
_foo is for private variable
m_foo is for private variable that also has its foo property
int foo
{
get => m_foo;
set => m_foo = value;
}
then why is it an m_
and not for example b_
since its a backing field
and you make a strong distinction
dunno
for exact purpose you are using it
since when was _ and m_ ever used at the same time?
the m_ notation is just old
it's used in unity's built-in packages
I think it makes my code readable too
because I have some properties
because those are old
i think it stems from microsoft having those guidelines for years
i wonder if they changed in new .net
yeah they dropped it altogether
what a pity
pity was m_
ill elaborate
when you indicate that a private field is a backing field, can you guarantee that the field is only used as a backing field for that property?
yes
if in the future the property would retarget to another field, or completely drop that field usages, will you rename the field
what do you mean?
what if several fields participate in single property?
should they all also be marked?
Make sure you prefix all the methods with F_ by the way, otherwise you might mistake it with a property, and it's more readable
was
int foo => m_a;
became
int foo => m_b;
what happens you rename m_a to _a ?
and the code that was written under assumption that the m_ is welded to the fact that its a backing field for a property would have to be rewritten as well?
that is done so you can write code that makes that assumption right?
code that discriminates fields
otherwise what purpose does it serve but cosmetic?
await UnityServices.InitializeAsync() => { GiveConsent(); }
how do i make it run GiveConsent automatically when the initializeasync function has finished?
.ContinueWith
Or put it below the async method since the method waits until the async method finished
like this?
Yes, that's how async-await works
ok thanks
Probably a good idea you get used to how it works and also why async void should only ever be used when you make Start and/or Awake asynchronous
Not knowing how it works can give you some serious issues
Sorry for late reply. What do you mean "became m_b"? How can I even happen?
probably it won't be that readable, cuz I won't understand whether this field has property or not
float _speed;
float _speedNormalized;
//was
public float Speed => _speed;
//became
public float Speed => _speedNormalized;
how?
Fields
private Type _name;
public Type name;
Properties
public Type Name;
you .. write it
"foo already contains definition for Speed"
yeah, how can it become?
you cannot change property
iirc
what
Over-time, as in with code changes :)
you cannot change property's get
So as development continues they change how that variable is derived
you have some weird understanding
maybe I do
yes, you cannot change methods
and properties
that doesn't make sense, because it will throw error
and that doesn't
public int MyProperty
{
get
{
// Custom logic to return a modified value
return myProperty * 2;
}
set
{
// Custom logic to set the value
myProperty = value + 1;
}
}
can you please explain where did you get this interesting misconception about properties and methods?
ive never seen this before
I don't get you
you are saying you cant change methods, what do you mean by this?
you cannot rewrite method or property
private string text
{
get => m_text;
set => SetText(value, true);
}
private string text
{
get => _text;
set => SetText(value, true);
}
are you suggesting a technical limitation or some conceptual/paradigmic limitation?
this throws error
that's what you have done
means that there was property a, that was rewriten as property b
that's just normal property
it doesnt mean there are 2 properties at the same time
The wording was confusing*
was/became is pretty clear
was means in the past
became means present
indicates a change
between past and present
I still don't get it
private string m_foo;
private string foo
{
get => m_foo;
set => m_foo = value;
}
m_foo and foo won't be ever changed in this example
because this example is not real code
in a real code base changes happen all the time
so how do you change them?
i type on a keyboard
Man im so confused xD
why are you?
it seems that we are talking about different things
Im trying to figure out what the issue is
he is saying an example of when u rewrite code.
I do it too.
so you just rename fields than
with F2
that's all
imagine if unity would rename all of their fields every engine update
they cannot do it
what do you even mean?
renaming fields is when you do it before script runs
Yes hes joking
joke
Also not during runtime, naming conventions dont matter during runtime anyway
you cannot
string foo = "blabla";
string foo = string bar;
right, now please read the rest of what i asked
and the code that was written under assumption that the m_ is welded to the fact that its a backing field for a property would have to be rewritten as well?
that is done so you can write code that makes that assumption right?
code that discriminates fields
otherwise what purpose does it serve but cosmetic?
they matter if you gonna make your cod readable
repost
your computer is never going to have trouble reading your fields
anyhow, besides the point
I am not computer
what cache is trying to say is that if you use the m_ prefix for variables that act as backing fields, and you then later change this behaviour, the prefix will no longer make sense
and it is not sensible to constantly rename your varaibles when working in larger projects
Especially when your functions are used by others, in the case of unity
it's like you write
string str1;
string str2;
string str3;
int int1;
int int2;
bool bool1;
Transform bar;
Transform foo;
it doesn't matter, but will you understand it then?
Cache also outlined some other cases where it would no longer make sense
Is your whole point that you can't give two fields the same names, hence why you resort to prefixing backing fields with m_?
yeah, you just throw that prefix away then
no one was saying to write it like this though
its not about renaming, its about a semantic load it carries, why do backing fields have meaning for code? Should they? Why code has to differentiate between kfield and field? What implications arise from that?
readability.
that's cosmetic aspect too
if you are after readability _ is more readable
I do use _
but you differentiate k fields
which makes them less readable
and puts on you the load to make assumptions about your fields
if this field is a kfield then... if not then...
I cannot give them same names, but yeah, naming fields with m_foo and their properties with foo sounds quite readable. Also more readable than _foo & foo, or foo & fooProperty
I think this is one of those things that comes with experience + he doesn't seem to quite understand what you are trying to say
so it seems
in c# its usually just _foo or foo if public and Foo for property .. In C++ its more common to see m_foo and kfoo
in Unity there are lots of properties (majority I would say) that are written with camelCase
kfoo?
its for constant (readonly) in c++
I see, I just use m_foo and foo
yeah, and k is used in Unity too
but returned with property
Yes but you are using C# so better use C# conventions
Do you realise that absolutely nobody resorts to naming their variables foo, bar, a, b, i, j or anything simplistic like this? You give actual readable names that explain the purpose. I have developed for years and very rarely I get naming conflicts, which is only the result of my own poor naming
So this is a very bad way to omit this, and definitely not any more readable over just using the regular naming conventions.
I understand you find it better, in which case go ahead and do it your own way. I can assure you however that the moment you start working in a team, your preference will most likely cause a big conflict because they will agree with you.
foo and bar are words without sense that were given for example
maybe
which..? the convention for properties has always been pascal case
private float _speed;
private float _maxSpeed;
private Vector3 _velocity;
@gray mural which of these is a backing field?
public string text
{
get
{
return m_Text;
}
set
{
SetText(value);
}
}
public float caretBlinkRate
{
get { return m_CaretBlinkRate; }
set
{
if (SetPropertyUtility.SetStruct(ref m_CaretBlinkRate, value))
{
if (m_AllowInput)
SetCaretActive();
}
}
}
public TMP_Text textComponent
{
get { return m_TextComponent; }
set
{
if (SetPropertyUtility.SetClass(ref m_TextComponent, value))
{
SetTextComponentWrapMode();
}
}
}
thats text mesh pro.
that's
Not even maybe. The moment you start adding linting packages or any sort of code convention validation code in your project, it will scream at you because of all the prefixes. Nobody does this anymore.
that is not written by unity
I thought we settled that old code related to Unity used to have this convention? This has never changed because they have no reason to, and they simply never changed the old code because of it.
Look up any modern Unity package and it will not have this convention
and its not their code, its developed by one guy, which asset they purchased
damn all that was developed by 1 guy?
yeah and still is afaik
It depends. If you had written e.g. m_speed - I would have instantly realised that it's backing field. With these information I can say that it's either just private variable or backing field
tmp_text is like 8k lines, that guy is a psycho
and thats like 1 class out of the entire package
alright, why do you need to know which one of these is a backing field?
8516
oh yeah, very very
probably _speed
im asking, why do you need to know
cuz I should know if I should set _speed directly or I do have its property that I have to set
right?
e.g.?
right? i dont know if its right, but i assumed properties are public interface
Pretty sure Vertx already gave you examples a few hours ago when you started the discussion
yeah, but if you open code and there is written m_speed, can you understand that you shouldn't set it directly?
why shouldnt it?
what stops me?
i have a complex code that sets it reads it all the same
theoretically speaking
A literal comment could explain it better than having a prefix everywhere
e.g.
private float m_speed;
private float speed
{
get => m_speed;
set => m_speed = value / 100f;
}
Why so focused on Unity anyway. Use c# conventions, then everyone can read code more easily ๐
Also @gray mural imagine you have these fields
private m_exampleField;
private _otherField;
public someOtherField;
private m_oneMorefield;
It gets confusing, especially since m means member and fields are all members, so not even sure how that helps with properties in the first place.
Plus a new guy may come on and then has to try and figure out why m_ is used ๐
yes, why?
unless you don't need to access it in another classes - it's private
because for that reason there are private methods
You dont need properties (usually) if its the same class.
pretty sure that guy should know why m_ is used.
for member and thats if you used another language usually.
those things are used widely, and its a convention, because properties initial and most important value is encapsulation
that doesn't matter, I think everyone knows m_
and using private properties achieves no encapsulation, as such they are useless
the only exception is protected virtual properties
that can be used to change object behavior in subclasses
you didnt know what kFoo is before, but thats also widely used, in other languages.
useless? why do I need to make property public if it's just used in my script?
why do you use private properties in your script?
in other languages. I have never learned C++
why do you use the wrong tool for the job?
Thats what im saying, m_ is not a C# convention
isn't it?
not anymore
its _foo
sorry?
i explained above
you mean for working in teams, or?
encapsulation
the main reason property exists
no encapsulation, means property is useless
it is better replaced with a method
He means no need for properties because encapsulation is used for wrapping around private or protected fields to expose to outside classes. Otherwise you wouldnt use Properties.
Do I really need to replace this by method?
private float m_speed;
private float speed
{
get => m_speed;
set => m_speed = value / 100f;
}
yes
yeah, I know what encapsulation it
Why not just let foobar use old conventions and let them figure out the drawbacks themselves? I remember when I learned of all these different conventions and I constantly switched to new ones because I thought they were better
It was quite a phase
how? is it more comfortable?
Ye for the better
private float _speed;
private void SetSpeedInternal(float value) => value / 100f;
haha,
speed = 1000; // 1
SetSpeedInterval(1000);
not more readable
you left the scope of cosmetic readability already
you are in the grounds of valid patterns and correct api design
this goes beyond just using a prefix
yes.
i tried ๐
@ashen yoke @swift comet @thin aurora @lean sail @winged mortar thank you all for your help and time!
๐ซก
Hello guys, not sure where to ask but..
I'm trying to generate a mesh based on Vector3, but when it comes to generating the triangles needed for the faces to show up I can't get my head around it, I'm very new to mesh generation... Is there a way to automatically generate triangles within unity? If not, do you have a recommended github page or algorithm that you usually use? Thanks!
you can describe the problem you have and we will help. I've seen procedural toolkit on github but never used it
is this error anything to worry about?
What does the stacktrace say?
ah, I do not remember, and it appears and disappears randomly.... When I get it again I shall check that!
It's probably an internal error. You can ignore those most of the time
If the error persists and/or troubles you during your work you can also try updating your Unity version, assuming you're not using an LTS version
float Foo {get; set;}
void Bar(Func<float> f) {}
Bar(() => Foo); // valid
Bar(Foo); // not valid
is this solved in later c# versions?
i dont see why it wouldnt convert it, help me understand what is preventing
hm maybe because you need a lambda to capture this ?
right
Might just be that the properties aren't considered to be of type Func
Instance methods can be converted to a delegate without a lambda. The problem is that C# just doesn't let you convert a property to a delegate.
right delegate holds the target
weird there must be some concrete reason why the opted out of it
Trying to work with splines from code is weird. How come the editor has more info on the knots than the code does, I can't even say if the knot should be continuous in code
with AnimationCurve?
the Keyframe struct has that
Use AnimationUtility.SetKeyLeftTangentMode or AnimationUtility.SetKeyRightTangentMode
oh thats editor
anyway all it does is modify the tangent values
you can just look up its source and do the same
that's a fair point
ahh there's actually a utility function called GetAutoSmoothKnot
im trying to understand where the tangent mode is kept
hm right in the
tangentMode: 1
why is it obsolete then
changes in editor serialize into this field marked obsolete, what
Could someone give some tutorial resources about how to protect script fields and etc
protect as in encapsulate?
or obfuscation encryption?
These?
Thx
love the name of the thread
Hey guys, how would I go about calling an event to individual objects? I have an OnDamage event in my health script that invokes on a character (which is a base class for the player as well as NPCs) whenever it takes damage, but as of right now, it invokes on EVERY character. How do I get it so that it only invokes on the damaged character? sorry if this is a silly q
Health component : ```CS
public class Health : MonoBehaviour
{
public UnityEvent onHeal;
public UnityEvent onZeroed;
public event Action onTakeDamage;
[SerializeField] float maxHealth = 100f;
float currentHealth;
private void Awake()
{
currentHealth = maxHealth;
}
void Start()
{
}
public void DamageHealth(float val)
{
if (val == 0) return;
ModifyHealth(-Mathf.Abs(val));
onTakeDamage?.Invoke();
}
Character class: ```CS
[RequireComponent(typeof(Health))]
public class Character : MonoBehaviour
{
Health health;
// Start is called before the first frame update
protected virtual void Awake()
{
health = GetComponent<Health>();
health.onTakeDamage += TakeDamage;
health.onZeroed.AddListener(Die);
}
protected virtual void TakeDamage()
{
Debug.Log(gameObject.name + ": Ouch");
}
protected virtual void Die()
{
// base class does nothing!
}
}```
did not know that was a thing, ty
i dont see an issue here
why not?
so what happens? you say its invoked on every character
but each of the health comps is unique right?
ok
put a breakpoint in DamageHealth
step through see whats going on
do you override Awake?
do you call base.Awake()?
in the override
I call the base awake function yes
any errors?
i am an actual fool
the only problem was the inherited NPC class, did not call the base TakeDamage() function from the character class...
well thank you anyway, if not for my stupid mistake I would not have found out about the sick CS code feature
ok so i have a player management script which manages all the collisions with other things (except movement related). I have a list of structs with a string called tag and a unity event. if a collision happens and the tag of the collider matches one of the tags in the list then the corresponding unity event is run. all works fine. a nice modular way of managing things like teleporters, coins, level loading areas e.t.c. it just checks a tag and runs some functions.
but I want to use my level loading function (which is in my game manager script) but the game manager is a don't destroy on load object and so i can't reference its functions with the inspector in the unity event (its created when the game loads only once and never gets destroyed, it doesn't exist in the levels by default and must be created in the loading scene(i can make it whilst in development but it won't be there in shipping)), i can get a reference to the game manager script in the scene when it does exist but how would you go about then referencing functions in it after that as i can't use the unity events in the inspector
i thought maybe a bool saying the functions is in the gm script and then a string with the name of the functions which somehow runs them but it feels a bit janky and was wondering if anyone could thing of a better solution
playerManager - the struct (shown in inspector) :
public struct CustomCollisionEvent
{
public string targetTag;
public UnityEvent eventsOnTrigger;
public string[] eventsInGMScript;
}
playerManager - on collision:
private void OnTriggerEnter2D(Collider2D other) {
foreach (var eventItem in collisionEvents) {
if (other.tag == eventItem.targetTag) {
eventItem.eventsOnTrigger.Invoke();
//run gameManager functs
}
}
}
playerManager - get game manager script referance:
void Start() {
GM = (GameManager) GameObject.Find("gameManager").GetComponent("GameManager");
}
gameManager - level load:
public void LoadLevel(string LevelID) {
SceneManager.LoadScene(LevelID);
}
sandbox it, create some component that has a bunch of methods that do common things, including call gm methods
so you serialize calls to that component which in turn calls gm at runtime
also called facade
no not facade thats different thing
thanks, idk why i didn't think of that. appreciate the advice.
would that effect efficiency that much?
thx, your a lifesaver. i just got myself all confused XD
actually one delegate invokation + direct call
oh youd have to locate the references to desired objects as well in awake
all adds footprint but marginal
depends on how you locate your managers
if using GameObject.Find() then yes thats very intensive
something like this?
void Start() {
GM = (GameManager) GameObject.Find("gameManager").GetComponent("GameManager");
}
public void LoadLevel(string data) {
GM.LoadLevel(data);
}
and have this one in the scene
game manager is a singleton
Hey I'm making a small platformer game but I'm having some trouble with the walljump mechanic. Is there any way I can send my code here or something if someone could help?
that code is in the sandboxing script. which isn't a singleton and is in each level
so if game manager is a singleton why are you using Find
shouldnt you be using GM = GameManager.Instance;
i need advice, im tinkering with a top down 2d sandbox game and im using a multi layered tilemap system for the world, my terrain gen will always be slow with a normal SetTile(); nested x & y for loop system even with me already chunking it up,, sooo i want to try use a List<int[,]> to generate and store the layer data as "raw" so i can use threading without Unity API issues. then once all the raw terrain data is made apply it with SetTile() without threading to the layers with something like SetTilesBlock();.
my issue im having is handling the List<int[,]> raw data its getting more complex than im good at dealing with
so i want to ask, should i keep pushing for this work around system, or just not use threading for my world generation. also any info on a Unity API safe threading method is also appreciated
slow as in? you are regenerating chunks around player as you go?
@me when you have a resolution, I am interested in this aswell - I had issues with the composite collider being slow
hm what i mean is you can treat tile system as just renderer
then chunks become renderers
you walk around you swap around chunks around players
"redrawing" them from backing data
i dont know how deep you are into tile system, so its just an idea
i plan on doing something like that at some point, but right now just want to get it running like it did before
the last version of the world gen and game as a whole used one scene for the world, switching between game "biomes" but using scenes is just better
my code is a huge mess right now but i can send it if that might give you an idea on what im trying to do
and also to tell me why im dumb here and there lol
sorry im very tired, i can give surface level ideas but i cant delve into code
thats okay, help is help!
my first version used a WaitForSeconds between every chunk
did you profile the generation as is?
but that was slow
what was the purpose of wait for seconds?
to make it wait before making the next chunk as i couldent use the threading method i know how to use as, API issues or whatever redit was saying
thats not how it works
i mean it just doesnt affect the total generation time
i know its bad but without the async threading with the int[,] idk how else to do it
i know, but it keeps the fps doing something
did you profile it?
i dont feel i need to, i know why its slow
on frame one it needs to loop through up to 2500x2500 then the chunks layers, etc
yes and still profiler can show you the bottlenecks
even with seemingly clear algorithms
how do i use it like that?
for example do you use flyweight pattern?
idk what that is
its when instead of allocating a new tile object for each cell, you insert one tile of that type in all cells of that type
meaning for 2500*2500 you have say max of 20 objects created
and the rest is simple "insert reference" in a loop
but i havent used unity tile system, i only wrote mine previously
https://hatebin.com/hhlkamlnmy
My code for movement of my character in 2d platformer. Everything working as I'd like except wall jumping. I think this is because I limited my velocity left and right, so when trying to walljump with a value higher than that it just leads to a failed walljump. Not sure how to exclude the limit from my walljump code.
im using a rule system like sorta what minecraft does for its older worldgen
so stuff like
if (layer == 0) { rawWorldLayerData[0][x, y] = 0; }
that calls for abstraction
i have a 2d platformer only 3 moves left,right,jump it's probably going to be easy to convert it to mobile right?
how much time does this take without any tile allocations?
the whole generator without unity tiles
so without any rules that set tiles?
with rules but without actually allocating the final tile
just skipping as if it was created
so just skip the final ApplyRawData() method i have, then the only data being stored is the raw int[,]
let me check rq
takes about 11 seconds to load in without the data being set onto the tile map
the only other thing is my backdrop code, and i already have that as good as i think i can get it
void GenBackdrop()
{
Vector2Int size = new Vector2Int(worldWidth * 2, worldHeight * 2);
activeBiomePipeline.backdrop.origin = Vector3Int.zero;
activeBiomePipeline.backdrop.size = new Vector3Int(size.x, size.y, 1);
activeBiomePipeline.backdrop.ResizeBounds();
activeBiomePipeline.backdrop.BoxFill(Vector3Int.zero, activeBiomePipeline.backdropTile, 0, 0, size.x, size.y);
activeBiomePipeline.backdrop.transform.position = new Vector2(-worldWidth / 2, -worldHeight / 2);
}
its just that
ah one sec
11 seconds is at the same time a lot, and not much
the IEnumerator for GenMap will be removed, just haven goten to it
public IEnumerator GenMap()
{
activeBiomePipeline.worldLayers.ForEach(layer => { layer.ClearAllTiles(); });
for (int l = 0; l < activeBiomePipeline.worldLayers.Count; l++)
{
for (int x = 0; x < worldWidth; x += chunkSize)
{
for (int y = 0; y < worldHeight; y += chunkSize)
{
LayerGenerationPasses(x, y, l);
chunkCount++;
yield return new WaitForSeconds(0.06f);
}
}
}
StampPlacement();
}
private void ApplyRawData()
{
for (int l = 0; l < activeBiomePipeline.worldLayers.Count; l++)
{
for (int x = 0; x < worldWidth; x++)
{
for (int y = 0; y < worldHeight; y++)
{
activeBiomePipeline.worldLayers[l].SetTile(new Vector3Int(x, y, 0), activeBiomePipeline.gameTileManager.tiles[rawWorldLayerData[l][x, y]]);
}
}
}
}
public void LayerGenerationPasses(int startX, int startY, int l)
{
Debug.Log("running LayerGenerationPasses");
for (int y = startY; y < startY + chunkSize; y++)
{
for (int x = startX; x < startX + chunkSize; x++)
{
float mainPerlinValue = FractalBrownianMotion(x / activeBiomePipeline.mainNoiseSettings.noiseScale, y / activeBiomePipeline.mainNoiseSettings.noiseScale,
activeBiomePipeline.mainNoiseSettings.octaves, activeBiomePipeline.mainNoiseSettings.lacunarity, activeBiomePipeline.mainNoiseSettings.persistence);
//Layer0 Rule
if (l == 0) { rawWorldLayerData[0][x, y] = 0; Debug.Log("running Layer0 Rule"); }
}
}
}
remove debugs
thats the bulk theory ive been using, just been remaking it
console spam really affects times in editor
oh yea, they were just there for testing
does what im doing make sense though? im not good at world gen but so many thing need it so i gotta get good at it at some point
you mean using SOA?
or what exactly?
most of it is just that, looping
things to note
too many reference types in use
cache things like activeBiomePipeline.mainNoiseSettings.noiseScale
in a struct once
create a struct Params shove all values you need into it
because each dereferencing of a heap object that is not in the cache is a cache miss and as a result a memory roundtrip
noted,
jagged arrays always were faster than mdim arrays
a single array is even faster
harder to write code tho
yea phind told me that lol
sure
show FractalBrownianMotion
private float FractalBrownianMotion(float x, float y, int octaves, float lacunarity, float persistence)
{
float total = 0;
float frequency = 1;
float amplitude = 1;
float maxValue = 0;
// Add the random offsets to the coordinates
float xCoord = x + xOffset;
float yCoord = y + yOffset;
for (int i = 0; i < octaves; i++)
{
total += Mathf.PerlinNoise(xCoord * frequency, yCoord * frequency) * amplitude;
maxValue += amplitude;
amplitude *= persistence;
frequency *= lacunarity;
}
return total / maxValue;
}
hm another thing to note is that
[FreeFunction("PerlinNoise::NoiseNormalized", IsThreadSafe = true)]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern float PerlinNoise(float x, float y);
if you find some pure c# noise library that is actually considered fast, some simplex noise lib, you most likely will shave a lot from that time
phind linked me to a github for Fast Noise but for the life of me i couldent figure out how to use it
hm?
OH ive been trying to send a photo lol
thats the peak
game freezes when i press the world gen button on the main menu, then once its got all the stuff done it loads
is that in VS or project settings?
which unity version?
im on unity 2019.4.31f1
then only build will have optimizations if its not there
when i do proper tests of the speeds i build
its habit for me
i only use play mode for quick tests, then once whatever i made is working okay i do a build
ok so its 4 seconds?
let me check in build
8 sec in build with a 1000x1000 world with no tiles being set, just the rawWorldLayerData
850m of ram from TM
so thats not the best at all
check profiler, what is taking most time
how do i check that, i only know how to look at the basic read out
switch to hierarchy, its simpler
but first i advice to rerun it with small map
otherwise it will lag like crazy
wdym switch to hierarchy
small map?
enable deep profiling
its on already
into backdrop or worldgen
hm
a assume worldgen
^ thats the code for that
well it seems unity tilemap should be dropped alltogether
can you expand it?
i assume it allocates new tile for each cell
anyway
thats the flyweight part, its later
keep expanding worldgen
thats what i would from this point, shave off all the time its possible on a single thread exclusively in worldgen
right
so eliminating most things i said earlier, you would look at something like 300ms
for 100*100
thats still 187 seconds if my math is correct for 2500*2500
which is ..
unfeasable
yeaa
here is the other half btw
as users may simply not have enough of it
hm strings huh
guess it deserializes transform? and copies name?
probably also marshalling
all the things i keep seeing say its fine if its slow as its just the start of the world and doesnt effect the game, but these speeds are with only the backdrop
not the 4 tilemap layers that are all assigned
and not on every save load
rimworld is limited to 300*300 i think, for a reason
mostly pathfinding costs, and enumerations on all the pawns
the only radically faster, more or less guaranteed solution will be using JobSystem to generate the data
and for rendering you need to go procedural mesh approach
jobs scares me a lot
thats the fastest way
yes you will have to completely write everything from ground up differently
its mostly automatic threading
you only need to learn to write the jobs themselves
pass the data, use the data from native collections, process it, return, the job system will run them in parrallel automatically
assuming that cuts costs on average 4 times, maybe more, 6? maybe more
you are still left with memory problem
assuming you use highly optimized rendering using mesh generation, that should be fine at runtime
if my math is correct a single 2d int array of 2500*2500 would take about 24414 mb
Is making foreach loop with e.g. ~50 circles like 10 times per second efficient?
since the job is not io intensive (you cant even do io in job) the number of jobs should be equal to number of logic processors to avoid the cost of thread switching
the only reasonable solution to having a world this large is not having it as tiles/grid
or, loading and writing chunks to disk
dynamically like its done in some games using quadtree
you will be storing the quadtree nodes on disk
basically minecraft
ill look into this stuff, i still want to use the tile map system but ill tinker with more options for optimization
my plan was to store the world/save as a file
still is i guess but small steps or something
gyat
I'm making an open world 3d top down game, when player is obstructed by an object, should I fade the object or should I draw player silhouette on top? Performance wise?
is performance really that important? something like that could be achieved with shaders
Renderer feature!
The game stays in bag state after i close the bag. So i can only close and open the bag one time. How do I get the state to change back to freeroam properly? Here is the code and example of the issue
!code
๐ Large Code Blocks
Large code blocks should be posted as links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/
https://paste.myst.rs/, https://hastebin.com/
๐ Inline Code
Surround code with three backquotes. Not quotation marks.
To get C# formatting the first line should only contain cs or csharp.
Add a comment with a line number if there is an error message.
```cs
// Your code here
```
Do not share screenshots of code unless requested.
a powerful website for storing and sharing text and code snippets. completely free and open source.
where do you switch back to FreeRoam state
line 137
but it can't run
why cant it run?
switch 137 and 136 real quick
I think you're printing the wrong thing
It invokes itself before changing the state?
I suck at reading recursive code tho
Actually nvm, I think I read it wrong.
i switched them, nothing changed
which line is that debug.log that spams
well they were in wrong order anyway, you put Changed To logging, before actually setting it
anyway I'm not finding that debug.log that spams , which line
might be checking the wrong thing
cause the one log does stay it goes to FreeRoam
Whichever one is spamming Bag Not seeing in this script
let me check for it
anyway if it's in another script you're not passing the state correctly
cause it does hit that Debug.Log on 137 so it's reaching it and switching it
you're just looking at the wrong log
keeping that enum in UI code is kinda smelly
it should be some type of global enum
what if you don't want to move if bag is open or w/e else
Or did I read it wrong, I'm pretty confused by what that invoke does.
It's invoking onBack and the method it's inside is taking in an action called onBack.
If it's using new input system, is it invoking the same event that runs the method it's inside?
But then again, wouldn't that just be a stack overflow...
Does anything change if you set the state before the invoke?
Anyway I'm not the best at reading events so if that isn't the issue, I'd best stop guessing tbh.
if that invoke is meant to control the enum state somewhere it should be invoked in the action
like Action<MyEnum>
then a simple switch / if statement in the listening classes
the one spamming bag is in my playermovement script
hmm If I were you, I'd refactor this a bit
is there any downside to using UI Image components on a world space canvas rather than using a sprite renderer?
is it possible to see the used Unity version of a shipped game? maybe from the given .dll files? in the metadata?
different usecases , also not a code question
srry wasnt really sure where to ask
even if there was we don't discuss modding/decompiling on this server
where to ask for this then?
another discord that deals with modding / general coding
I have 2 triggers that have these tags but they arent being detected when I enter them. I assume its a problem here?
Put this as the first line in the method, outside the if blocks:
Debug.Log($"collided with {other.gameObject.name} that has the tag {other.gameObject.tag}");
If that doesn't show up then go through https://unity.huh.how/programming/physics-messages
I have no idea why but whenever I call Sword.Use() the variable _isSwinging is always set to true.
I tried debugging it by putting a breakpoint on the set-accessor and it only breaks on awake, after that there are no other breaks.
YET the _isSwinging variable is always true whenever I try to call Use()
https://gdl.space/aruwewucuk.cs
(Use() only gets called once every MouseButtonDown(0) and the variable is not changed anywhere outside this class)
becasue on line 77 you're literally just setting it to true?
isSwinging = true;
Yes, but it never even goes to that line, since when I first call the Use function it is already set to true.
I literally put a breakpoint in the start of the use function
if (isSwinging) return;
This property is public:
public bool isSwinging
so it could be getting set from anywhere
maybe make the setter private
so it can't be changed externally
I just did that to be able to put a breakpoint on the setter, it was private only before, same issue
then it's coming from a previous call to Use
It's already set to true the first time Use gets called or the first time the breakpoint of Use gets called, thats the issue
I would say you're probably just misinterpreting something
Assuming you make the setter private, it can't happen
Add Debug.Log in Awake and in the setter and show the console when you run
where is the "Mouse button down" coming from
and "we are in the isSwinging propery" setter or getter? Printing before or after setting it?
WeaponController Class
if (Input.GetMouseButtonDown(0))
{
print("Mouse button down");
player.Stats.Weapon.Use();
}```
setter and after we are setting it
was the code you shared the full script?
also do you have Collapse enabled on your console window?
Yes, and no I did not have collapse enabled
@leaden ice I think I found the problem, unity keeps my variables even after restarting the play mode, no idea why that happens but the counter didnt reset after I restarted the play mode
That would only happen if this object is like... a ScriptableObject or a prefab or something
and only if there was no domain reload when you hit play
yeah makes sense
Okay I give up, even when checking that box and restarting Unity I still have the same issue.
anyway to make the arrow rotate towards the player?
Align the arrow with the velocity/direction of the object by using transform.forward = ....
What is the type of Weapon ?
What do you mean with type?
Is it a MonoBehavior ?
Yes the subclass Weapon is a MonoBehaviour
hi first time here!
i already searched the internet and i cant find anything that works or anyone with the same problem.
i have a position where i want to check if the player is standing there. I decided to use BoxCast to check but it dosent detect the player.
Debug.Log("Hit Something");
} else {
Debug.Log("No Collision detected");
}
position: is where i want to check
start: is the object that is there where i will take the collider to get the size (collider is trigger)
and layer is set to the same layer then the player.
but it doesn't detect the player if its inside.
All layers are set to collide with each other.
i also check with Gizmos and it is the right spot i want to check
Gizmos.DrawWireCube(position, start.GetComponent<Collider2D>().bounds.size);
Is it correctly Instantiate ?
Looks like so yea
You might want to use https://docs.unity3d.com/ScriptReference/Physics.OverlapBox.html
transform.rotation = Quaternion.Euler(180f, 0f, 0f);
didnt work
public class Projectile : MonoBehaviour
{
public float lifetime = 5f;
public float destroyDelay = 0.2f;
private bool hasHit = false;
private GameObject playerObject; // Reference to the player object
private void Start()
{
Invoke(nameof(DestroyProjectile), lifetime);
// Find the player object by layer
int playerLayer = LayerMask.NameToLayer("Player");
GameObject[] playerObjects = GameObject.FindGameObjectsWithTag("Player");
foreach (GameObject player in playerObjects)
{
if (player.layer == playerLayer)
{
playerObject = player;
break;
}
}
}
private void OnCollisionEnter(Collision collision)
{
if (!hasHit)
{
hasHit = true;
// Perform any actions or effects on hit
DestroyProjectile();
}
}
private void Update()
{
if (playerObject != null)
{
Vector3 targetDirection = playerObject.transform.position - transform.position;
Quaternion rotation = Quaternion.LookRotation(targetDirection, Vector3.up);
transform.rotation = rotation;
}
}
private void DestroyProjectile()
{
// Perform any cleanup or effects before destroying the projectile
Destroy(gameObject, destroyDelay);
}
}```
also didnt work
Would it possible that some calls Use before you think ?
I mean not that it would make sense, I also checked with breakpoints, all really strange
It is possible that your model is not correctly align with its forward.
the arrow model?
if thats what you mean
Might be able to just change the rotation in import settings.
Although if you are already using the same arrow model in other places then those would rotate, too, if you change it now.
omg thank you so much it works now! i feel so stupide rn ๐ Thank you!
No. Where the blue arrow points in relation to the arrow ?
i tired rotating in the transfrom through the inspector if thats whatcha mean
im sorry if im being slow but what blue arrow?
I mean the import settings for the 3D mesh
When you select an object, there is 3 arrow. 1 blue, 1 red, 1 green
how do i access that
oh i thought the literal arrow game object
rotate it to the blue?
So it points in the blue direction.
why create a child if i can just rotate it to the blue?
To not fuck up the rest of your game.
oh ok lol
create a child to the arrow or...?
i dont understand lol
||sry btw||
Prefab: Arrow
- Arrow Object (With Script)
- Arrow Visual (With Renderer)
I am super confused - I have an object with a rigidbody, I have a camera with a raycaster, and I have a childobject of that rigidbody with a collider
Now - I'm trying to detect if the raycast hits the childobject, but that's not working - unless I either remove the rigidbody, or add a rigidbody to the object with the collider as well. I am SO confused. Why does it happen?
there are 3
Yeah nvm the import settings, might be better to just do what Simferoce is suggesting.
Basically if a character is firing arrows at a certain rotation, but the rotation is funky, you can make the 3D model be a child of the actual (empty) object that's being fired.
Then just rotate the child object (with the model) to face the right direction.
Try tht
it kinda works....?
ill send a vid
However, I m pretty sure you gonna need to rotate it in the inverse of the rotation being apply
Not the actual forward
But something like the inverse of the forward in your situation
Hi there people, I am in need of help because I've been strugling with the same issue for MONTHS now....
I've tried many methods and no one works for me
This is a simple camera follow script I made based on the simplies tutorial I've found:
using UnityEngine;
public class VehicleCameraController : MonoBehaviour
{
public float cameraSpacing = 6f;
public float followSpeed = 100f;
public float rotationSpeed = 100f;
private float angle;
private float distance;
private Vector3 cameraPosition;
private Vector3 smoothPosition;
public Transform target;
private void FixedUpdate()
{
distance = Mathf.Abs(target.position.magnitude - transform.position.magnitude);
cameraPosition = target.position - (target.forward * cameraSpacing);
smoothPosition = Vector3.Lerp(transform.position, cameraPosition, (followSpeed + distance) * Time.fixedDeltaTime);
transform.position = smoothPosition;
angle = Mathf.Abs(Quaternion.Angle(transform.rotation, target.rotation));
transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, (rotationSpeed + angle) * Time.fixedDeltaTime);
}
}```
For some reason values higher than 100f for both 'followSpeed' and 'rotationSpeed' variables just don't work, this wouldn't be a problem for a low velocity vehicles, but this vehicle goes 600km/h and faster leaving the camera waaaaaaaaaaaaaaay behind it and I can't compensate it any way even if I square the distance or multiply by the distance instead of adding it, it doesn't work, I can't make the camera to catch up with the vehicle.
I am about to give up, I just can't figure out what it is, I've tried to run the camera calculations in both Update() and LateUpdate() and it looks like crap, too much jitter in both of those methods.
If you have any sugestion, please, I would appreciate it, may be the issues is somewhere else, not necesary in the camera itself.
it sometimes shoots in the wrong direction
the closer i get to the enemy the easier it is to see it
@steady moat
I imagine you have an issue in your script.
should i send it?
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.
if you dont trust the link ill send the full script here because some people didnt want ot click it in the past lol
You could set the rotation here
And remove the rotation from your arrow script.
Only need to set it once
set it as the second one?
the one you circled?
Yes
transform.rotation = Quaternion.Euler(0f, 0f, 90f);
is that good?
or should i do it in a different way?
You should not use a lerp function for what you are doing. Lerp is a percentage which is bigger the farther you are.
What function could be used instead?
What you want ?
Why you use a lerping ?
The way (heh) lerp works is, the first parameter you give it a start position.
The second parameter is the end position.
The third parameter is a value between the start and the end.
If start is 0f and end is 100f, 0.5f in the third spot would make it return 50f.
Because it's 50% of 100.
So a lerp with third value of 1f is pretty much the same as just having it follow the end point with no smoothing.
Probably why at really big values it's no longer truly lerping.
Also fixed update runs 50 times per second, so if you move at truly insane speeds it would probably get choppy eventually.
I want the camera to follow a vehicle, but I don't want to aprent it directly, because it looks motionless and weird
I want a camera to smoothly follow the vehicle
Does anyone have a solution for using SQLite with Unity that doesn't involve using the Mono version? I'd prefer to use the System version
Define smoothly.
use cinemachine
Have you tried cinemachine?
I haven't tried it at crazy high speeds but it's official and free.
That is unless you wanna code the camera yourself, which I can respect.
You would have the same issue would you ?
not with the correct settings
What are the correct settings O.o
ok
I want the camera to keep x distance to the vehicle, for example I want it to be 6m bahind it, but when it accelerates I want it to be left behind a little bit and when the vehicle deselerates, I want it to get a little beet closer
(In this situation)
missing from the description of this problem is a description of how the car is moving
Cinemachine has all the settings to simulate what he wants, with damping, distance, etc.
ArgumentNullException: Value cannot be null.
Parameter name: _unity_self
UnityEditor.SerializedObject.FindProperty (System.String propertyPath) (at /Users/bokken/build/output/unity/unity/Editor/Mono/SerializedObject.bindings.cs:74)
UnityEditor.UIElements.Bindings.SerializedObjectBindingContext.BindPropertyRelative (UnityEngine.UIElements.IBindable field, UnityEditor.SerializedProperty parentProperty) (at /Users/bokken/build/output/unity/unity/ModuleOverrides/com.unity.ui/Editor/Bindings/BindingExtensions.cs:169)
UnityEditor.UIElements.Bindings.SerializedObjectBindingContext.BindTree (UnityEngine.UIElements.VisualElement element, UnityEditor.SerializedProperty parentProperty) (at /Users/bokken/build/output/unity/unity/ModuleOverrides/com.unity.ui/Editor/Bindings/BindingExtensions.cs:113)
UnityEditor.UIElements.Bindings.SerializedObjectBindingContext.ContinueBinding (UnityEngine.UIElements.VisualElement element, UnityEditor.SerializedProperty parentProperty) (at /Users/bokken/build/output/unity/unity/ModuleOverrides/com.unity.ui/Editor/Bindings/BindingExtensions.cs:39)
UnityEditor.UIElements.Bindings.DefaultSerializedObjectBindingImplementation+BindingRequest.Bind (UnityEngine.UIElements.VisualElement element) (at /Users/bokken/build/output/unity/unity/ModuleOverrides/com.unity.ui/Editor/Bindings/BindingExtensions.cs:1126)
UnityEngine.UIElements.VisualTreeBindingsUpdater.Update () (at /Users/bokken/build/output/unity/unity/ModuleOverrides/com.unity.ui/Core/Bindings/VisualTreeBindingsUpdater.cs:272)~
Can anyone tell me what this error is about? I can't really find the source of the issue
Sounds like a basic cinemachine camera with damping
Unity bug
Yeah this. It's all built-in already. Super easy to set up and endless tweaks to get the effect you want.
I've tried and I basically get same result
you did something wrong
Did you try to modulate the parameter of the Lerp ?
that's literally damping on cinemachine mate.
also the fact you have jitter in LateUpdate means your car is probably not using interpolation
Damping is a lerp isnt ?
No
Not quite inderstand this
Does anyone know if there is a way for me to check if the instantiated gameobject is unique? Maybe a way for me to debug the issue
I'm sure there's a mathematical difference, but prob similar.
Add a value to modulate the paramter of the lerp to increase the rigidity.
Give it a GUID?
What would it be ? Because this could be exactly what our friend needs.
Object.GetInstanceId();
I would love to avoid Cinamechine if possible, it's kind of complex to understand and has a lot of configurations and setup to do, I would prefer to implement something simple
Yea the instanceId is the same even after restarting the play mode :/
qquite the contrary. Camera motion is complex and cinemachine makes it simple
a few clicks and you're done
as opposed to MONTHS (your words) of fiddling with scripts
Your something simple will very fast turn into something complex. Better learn to use the right tool for the job. Me personally I have not written a cam controller since 2018
Idk but there's Lerp and SmoothDamp functions.
But honestly, he should just use Cinemachine. It has this built in and so easy to use.
Cinemachine 
Yup same. This was one of my biggest deterrents actually when learning Unity. I just couldn't make a decent camera controller, I would spend weeks on copying code and didn't fcking understand a thing lol
Let me try smoothdamp first
I mean Cinemachine is truly something that should be use, however I think that it will not dirrectly fix the issue of our friends.
Yeah ok but how can I find out what the source is? How to fix it so to say?
There isn't any fixing it because you didn't cause it
Try to clear it, and if it doesn't clear, restart Unity. If it still doesn't let you enter playmode, submit a bug report.
how can you be so sure I did not cause it?
Yeah ok but maybe I screwed something up with using the built-in libraries wrong?
Then the error would reference the file you wrote
Jesus, gonna sit there and fucking argue because the answer isn't what you were expecting
I m pretty sure you can safely ignore this error. It is an Inspector error. That being said it could be useful which object is in error.
Nein, SmoothDamp didn't help
Try to play with the damping value with the following.
using UnityEngine;
public class VehicleCameraController : MonoBehaviour
{
public float cameraSpacing = 6f;
public float followSpeed = 100f;
public float rotationSpeed = 100f;
public float damping = 1.0f;
private float angle;
private float distance;
private Vector3 cameraPosition;
private Vector3 smoothPosition;
public Transform target;
private void FixedUpdate()
{
distance = Mathf.Abs(target.position.magnitude - transform.position.magnitude);
cameraPosition = target.position - (target.forward * cameraSpacing);
smoothPosition = Vector3.Lerp(transform.position, cameraPosition, damping * Time.fixedDeltaTime);
transform.position = smoothPosition;
angle = Mathf.Abs(Quaternion.Angle(transform.rotation, target.rotation));
transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, (rotationSpeed + angle) * Time.fixedDeltaTime);
}
hm... that damping is pretty much the same as followSpeed
You know, I can't get the damping aproach
I am going to offset the target position
based on the distance between the camera and the object it follows
that should compensate
lol
Vector3.Lerp, Vector3.MoveTowards and Vector3.SmoothDamp give the same result
Values higer that 100 don't work
Show your code.
I came up with this:
using UnityEngine;
public class VehicleCameraController : MonoBehaviour
{
public float cameraSpacing = 6f;
public float followSpeed = 1f;
public float rotationSpeed = 1f;
public float angle;
public float distance;
private Vector3 cameraPosition;
private Vector3 smoothPosition;
public Transform target;
public Rigidbody rb;
private void FixedUpdate()
{
distance = Vector3.Distance(target.position, transform.position);
cameraPosition = target.position - (target.forward * cameraSpacing);
smoothPosition = Vector3.MoveTowards(transform.position, cameraPosition, (followSpeed + rb.velocity.magnitude) * Time.fixedDeltaTime);
transform.position = smoothPosition;
angle = Mathf.Abs(Quaternion.Angle(transform.rotation, target.rotation));
transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, (rotationSpeed + angle) * Time.fixedDeltaTime);
}
}
The:
smoothPosition = Vector3.MoveTowards(transform.position, cameraPosition, (followSpeed + rb.velocity.magnitude) * Time.fixedDeltaTime);```
Works exactly as:
```haskell
smoothPosition = Vector3.Lerp(transform.position, cameraPosition, 100f * Time.fixedDeltaTime);```
Well, yes, 100 times 0.02 is more than one
Lerp will instantly reach the destination
Read the documentation for the methods youโre using
I mean... like I told you earlier, the third number is a percent of a sort. And at 1f it's same as the end pos.
The only way out I see is that I can not use Unity methods, I have to write my own
no, you need to read the documentation.
you're using a hammer to drive a screw and then acting surprised when you get a bad result
MoveTowards's third argument is the distance to move. Lerp's third argument is the percentage to move.
SmoothDamp's fourth argument is the amount of time it should take to reach the target.
yep, lerp uses 0 and 1
Yeah, I see
with this information you should be good to go
So I used:
smoothPosition = Vector3.SmoothDamp(transform.position, cameraPosition, ref velocity, 0f);
And the result is pretty much the same, the camera keeps getting behid the ship
Did you read the documentation?
why would you use smoothdamp if you want the movement to happen instantly?
You are using SmoothDamp in a nonsense way.
what
By modulating the damping parameter you should be able to get a fairly good smooth. Try values like 90 or 99. (With lerp)
i mean, they're using SmoothDamp with a smoothing time of 0 seconds
i'm not even sure how that will behave
i guess it'll snap to the target instantly. probably.
Sadly the laptop I am currently working on is not the ebst to run Unity and a screen recorder
use SmoothDamp with a pretty fast smoothing time and the camera will very aggressive catch up with whatever it's following
But you can see the diference in distance when the ship is still, when it moes at 500 and faster
Show us the entire method again.
I am curious to see where velocity is declared, among other things
https://docs.unity3d.com/ScriptReference/Vector3.SmoothDamp.html
"Current, target, current velocity, max speed".
So your current spot is transform,position, your target is cameraPosition.
So you are moving something towards the camera?
I dunno what you put in velocity and you set the time to 0 (instant movement?)
So you are instantly moving something to the camera if I'm reading this right?
using UnityEngine;
public class VehicleCameraController : MonoBehaviour
{
public float cameraSpacing = 6f;
public float followSpeed = 1f;
public float rotationSpeed = 1f;
public float angle;
public float distance;
private Vector3 cameraPosition;
private Vector3 smoothPosition;
private Vector3 velocity = Vector3.zero;
public Transform target;
public Rigidbody rb;
private void FixedUpdate()
{
//distance = Vector3.Distance(target.position, transform.position);
cameraPosition = target.position - (target.forward * cameraSpacing);
smoothPosition = Vector3.SmoothDamp(transform.position, cameraPosition, ref velocity, 0f);
transform.position = smoothPosition;
angle = Mathf.Abs(Quaternion.Angle(transform.rotation, target.rotation));
transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, (rotationSpeed + angle) * Time.fixedDeltaTime);
}
}
Also, do not use such high speed...
I don't know how SmoothDamp behaves when the damping time is zero seconds.
Reduce your speed and the size of your map.
consider a non-zero duration.
What if I make everything slow, but I run the simulation twice as fast
none of this is relevant for the camera movement problem
Because the goal here is to make a fast racing game
also, if you want to sanity-check the camera positioning, just directly move the camera to the target position
if it still lags behind, then you have something else going on here
perhaps you are changing cameraSpacing elsewhere, for example
Ok, sohuld I do this un LateUpdate?
No, I didn't say to do that.
No, the name is wrong cameraPosition should be names targetCameraPosition
But that is something I was considering. It's possible that things are happening out-of-order and leaving the camera one frame behind.
i.e. the vehicle moves after the camera moves
This could cause it to appear increasingly far behind as the vehicle accelerates
Holy
there is something very wrong
private void FixedUpdate()
{
//distance = Vector3.Distance(target.position, transform.position);
targetCameraPosition = target.position - (target.forward * cameraSpacing);
//smoothPosition = Vector3.SmoothDamp(transform.position, targetCameraPosition, ref velocity, 0f);
transform.position = targetCameraPosition;
angle = Mathf.Abs(Quaternion.Angle(transform.rotation, target.rotation));
transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, (rotationSpeed + angle) * Time.fixedDeltaTime);
}```
