#Resources unique ID

1 messages ยท Page 1 of 1 (latest)

jovial shard
#

Going off from the previous post that i had with MrGadget.
#1076640055164162068 message

GeNa doesnt have anything like this so i am trying to make it myself, but i find myself needing a unique identifier for the tree that needs to be swapped out.
I dont really wanna add a Tree script on my tree that just sets a id... because i would have to do that for thousands of trees... Is there something that gives objects an unique identifier already by Unity? Im not sure if GetInstanceID() is something i should use.

Thanks!

wind gust
jovial shard
#

Design time

#

i place everything manually, can also do random but i didnt do it at runtime ๐Ÿ™‚

wind gust
#

is this a game where there's always going to be a host client?

jovial shard
#

well so far yes, im thinking of going headless dedi server but for now i guess a host client is easier

wind gust
#

This is something you need to decide now, because it will impact your architecture going forward.

#

if headless is the goal, plan for that now

#

With headless, what you don't want is thousands of trees in the server scenes - too much ram waste

jovial shard
#

true, well ok, since i am using STEAMWORKS for most stuff (now im on KCP for quick testing etc) i will stick to host client ๐Ÿ™‚

wind gust
#

ok...what you can do is create a Scriptable Object that has a Dictionary in it (not a SyncDictionary...just normal one)

#

Make an editor script to iterate all the harvestable stuff in the scene, and feed them into the SO dictionary at design time, so that becomes an asset that's included with the build and already populated

#

key to the dictionary will be Vector3 of the pos of the thing. Value will be a struct of what it is (GameObject reference), and it's rotation, and a prefab reference to a networked variant prefab of the same thing. That prefab variant will need to have a mask to hide the GeNa object or some code to shut off the renderer of the GeNa object

#

When the networked variant is spawned, it can have an OnStartClient override that looks up the SO Dictionary entry by its own spawn pos, take the GO reference from the entry, does GetComponent<Renderer> to get that and disable it. Might be able to just have that in the dictionary instead of the GO itself - play around with that idea.

#

In OnStopClient, it will need to re-enable that renderer so the GeNa object is restored

#

When player presses "H" (for example) to Harvest, client can call a CmdHarvest and in that you can do a raycast forward from player to nearest thing in front of player, and take pos of that to the dictionary to look up what prefab variant to spawn and where, with rotation

#

@jovial shard

jovial shard
#

Jesus that sounds good, thanks for the input! Explaining it like this might help me on my way, i hope i wont see too much issues going forward ๐Ÿ˜ฎ

wind gust
#

Then you can a) find all with that script, b) just have the variant call methods in that script to hide / show the thing, c) have OnValidate code to add itself to the SO Dictionary so you don't have to mess with an editor script.

The networked variant could have disabled art to show damage, have the loot stuff defined, etc.

#

@jovial shard Also put all your base and variant prefabs on a layer just for them. That will help you in your raycast using a layer mask to avoid hitting another player instead of the tree behind them.

jovial shard
#

hmm, yeah thats an option! I guess i should do that, now all my trees have Tree.cs script that implement IInteractable so i can detect it, but that works for multiple occasions haha, good call ^^

wind gust
jovial shard
#

it is yeah

wind gust
#

good use that - OnValidate to feed into the SO dictionary

jovial shard
#

aye, will do PeepoHappy

#

it all sounds fairly difficult to implement but i have a feeling its actually very easy to do ^^

wind gust
#

It's not that hard, really - it's not even a lot of code

jovial shard
#

well ๐Ÿ˜„ im gonna start right away on it ^^

wind gust
#

kk - let me know what you come up with - just keep things really simple.

jovial shard
#

alright will do ๐Ÿ˜Š ill let you know

wind gust
jovial shard
#

even tho i have Odin, i wont do that ๐Ÿ˜›

wind gust
#

If Odin can do it quickly, fine...just don't lose a day faffing around with that

jovial shard
#

well, what i got now on the Tree.cs

public class Tree : MonoBehaviour
{

    public GameObject networkVariant;

    private void OnValidate()
    {
        //Add to treesystem
        TreeSystem.Instance.resourceDictionary.resources.Add(transform.position, new CustomResource { objectRef = gameObject, rotation = transform.rotation, networkVariant = networkVariant});
    }
}
#

TreeSystem.cs

    public ResourcesDictionary resourceDictionary;

TreeSystem.cs has a NetworkBehaviour ๐Ÿ™‚

#

and its a singleton

wind gust
#

that won't work like that - needs to be a ScriptableObject with a Dictionary so you have an asset that's part of the build.

jovial shard
#

This is my Scriptable Object haha

namespace OLT.SO
{
    [CreateAssetMenu(menuName = "Configs/ResourcesDictionary", fileName = "ResourcesDictionary")]
    public class ResourcesDictionary : ScriptableObject
    {
        public Dictionary<Vector3, CustomResource> resources = new Dictionary<Vector3, CustomResource>();
    }
}

public struct CustomResource
{
    public GameObject objectRef;
    public Quaternion rotation;
    public GameObject networkVariant;
}
wind gust
#

ahh ok

#

that's looking right

jovial shard
#

added to my treesystem

#

all trees will be added to that upon OnValidate

wind gust
#

yeah should work

jovial shard
#

alright. let me continue pepeHihi

wind gust
jovial shard
#

im new to the Vector2Int and Vector3Int s

#

vector2 int wants 2 ints, but the position X and Y is set in floats, do i just floor them?

wind gust
jovial shard
#
    private void OnValidate()
    {
        //Add to treesystem
        Vector2Int key = Vector2Int.FloorToInt(new Vector2(transform.position.x, transform.position.z));
        TreeSystem.Instance.resourceDictionary.resources.Add(key, new CustomResource { objectRef = gameObject, rotation = transform.rotation, networkVariant = networkVariant});
    }

Fair enough ๐Ÿ™‚

#

i do get these tho, on the onvalidate method ๐Ÿ˜ฎ

#

that is when the game starts and when i save a script haha

wind gust
#

you have to create the SO asset first

jovial shard
#

i mean, i did

wind gust
#

and reference that asset, not the SO script

jovial shard
#

hold up

#

Yeah

#

that should just work Think

wind gust
#

TreeSystem.Instance is null at design time

jovial shard
#

i guess thats true, but not at runtime right?

wind gust
#

correct

jovial shard
#

it happens at runtime when i start it

#

i do see the NetworkSystems going gray, because i havent connected yet

wind gust
#

remember you're loading this dictionary at design time

#

OnValidate is design time only

jovial shard
#

oh

#

ohh i thought also when starting

wind gust
#

nope

jovial shard
#

aaaaaah mindblown

#

How would i ensure this to work on design time? ๐Ÿ˜ฎ

wind gust
#

log in OnValidate that spits out the SO Dictionary count?

#

don't use resources.Add either - you'll end up with millions of duplicates

jovial shard
#

i uhh, cant, it instantly errors about the nullref ๐Ÿ˜›

wind gust
#

resources[key] = value

#

if it's complaining that the SO is null then you have the wrong reference

jovial shard
#

Ok so i got this in the onvalidate

    private void OnValidate()
    {
        //Add to treesystem
        Vector2Int key = Vector2Int.FloorToInt(new Vector2(transform.position.x, transform.position.z));
        TreeSystem.Instance.resourceDictionary.resources[key] = new CustomResource { objectRef = gameObject, rotation = transform.rotation, networkVariant = networkVariant};
        Debug.Log(TreeSystem.Instance.resourceDictionary.resources.Count);
    }
#

which loops to

public class TreeSystem : NetworkBehaviour
{
    public ResourcesDictionary resourceDictionary;
}
#

and i dragged the SO into that resourceDictionary

wind gust
#

TreeSystem.Instance still

#

you can't use instance in OnValidate

jovial shard
#

haha dang

#

So treesystem should be a static class i guess?

wind gust
#

TreeSystem is on a scene object?

jovial shard
#

ya

#

on an empty object

#

with a NetworkBehav

wind gust
#

FindObjectOfType<TreeSystem>

jovial shard
#

fair enough

#

the debug log

#

not sure why it says 7 when theres only 6 trees

#

ah it started at 1 lol nvm ๐Ÿ˜„

wind gust
#

no, it's got a count of 7 entries

jovial shard
#

oh well no idea then haha i have 6 trees in the scene mhm

#

its fine, ill figure that out, atleast it adds to the dictionary now

wind gust
#

anything else got tree.cs on it?

jovial shard
#

nope ๐Ÿ˜ฎ

#

i continued on my networkprefab of the tree, added a networkidentity

#

now i guess it needs a script to toggle the other tree whenever its spawned in? (onstartclient)

wind gust
#

this is the variant of the base, right?

jovial shard
#

yes

#

๐Ÿ™‚

#

normal and network variant

wind gust
#

yeah in OnStartClient, take the pos, convert to Vector2Int, and dig the dictionary for the entry

#

Add a ShowHide method to Tree.cs

#

GetComponent<Tree> and call that to hide it. Call that again to show in OnStopClient

jovial shard
#

im not at the hardest part yet ๐Ÿ˜‰

wind gust
#

Putting the ref to that in the struct will simplify this code a lot

#
public struct CustomResource
{
    public Tree treeRef;
    public Vector3 position;
    public Quaternion rotation;
    public GameObject networkVariant;
}
jovial shard
#

oh ๐Ÿ˜ฎ

#

instead of objectref the Tree itself

#

nice

wind gust
#

resources[key] = new CustomResource { treeRef = this, position = transform.position, rotation = transform.rotation, networkVariant = networkVariant};

jovial shard
#

nice ๐Ÿ˜„ Im writing the OnStartClient thing now

#

the NetworkedTree.cs thats on the network variant

    public override void OnStartClient() {
        Vector2Int key = Vector2Int.FloorToInt(transform.position);
        CustomResource tree = FindObjectOfType<TreeSystem>().resourceDictionary.resources[key];
        tree.treeRef.Hide();
    }

    /// <summary>
    /// This is invoked on clients when the server has caused this object to be destroyed.
    /// <para>This can be used as a hook to invoke effects or do client specific cleanup.</para>
    /// </summary>
    public override void OnStopClient() {
        Vector2Int key = Vector2Int.FloorToInt(transform.position);
        CustomResource tree = FindObjectOfType<TreeSystem>().resourceDictionary.resources[key];
        tree.treeRef.Show();
    }
wind gust
#

I'd forgotten this actually works - it ignores the Y ๐Ÿ™‚
Vector2Int key = Vector2Int.FloorToInt(transform.position);

jovial shard
#

yeah it didnt throw an error, so i guess it would format itself ๐Ÿ˜„

wind gust
#

You can use TreeSystem.instance now ๐Ÿ™‚

jovial shard
#

oh yeah true

wind gust
#

Single ShowHide method with a bool
tree.treeRef.ShowHide(true);

jovial shard
#

ight ๐Ÿ˜„ is toggling the render really enough ? ๐Ÿ˜ฎ

wind gust
#

GameObject.SetActive(switchBool);

#

That will knock out the collider, renderers, etc. - probably a lot safer that way

jovial shard
#

hahaha got it ^^

#

now i just need to spawn in the Networked tree

#

and then everything is ready to go i guess ๐Ÿ‘€

wind gust
#

should be. Might want a spherecast forward just in case player isn't looking right at the tree

#

don't want a ray to miss due to unfortunate angle

jovial shard
#

hmm yeah this is my current script detecting stuff

    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit, 100))
            {
                if (hit.transform.TryGetComponent(out IInteractable interactable))
                {
                    interactable.Interact();
                }
                Debug.DrawLine(ray.origin, hit.point);
            }
        }
    }

wind gust
#

nope

#

Need to sphere cast inside a Cmd

jovial shard
#

๐Ÿ˜ฎ

wind gust
#

so it's server side to see if there's a tree in front of player - forget the camera

#

just go from player's pos forward

jovial shard
#

Is that allowed to be on the PlayerInteract : NetworkBehaviour?

wind gust
#

is what allowed?

jovial shard
#

putting that logic in there

#

on a script thats attached to the player

wind gust
#

inside a Command?

jovial shard
#

yeah

wind gust
#

sure

jovial shard
#

๐Ÿ˜ฎ awesome, versatile

wind gust
#

can't use camera server-side

#

nor mouse

jovial shard
#

hmm thats clear ๐Ÿ˜„

wind gust
#

but you can spherecast forward from player object on server

#

call the Cmd from a keypress like H for harvest

jovial shard
#

Yeah ๐Ÿ™‚ and now i have to check on how to get the player that called the command

wind gust
#

that's in our docs

jovial shard
#

let me hit the docs rq

#

exactly XD

wind gust
#
    void Update()
    {
        if (isLocalPlayer && Input.GetKeyUp(KeyCode.H))
            CmdHarvest();
    }

    [Command(requiresAuthority = false)]
    public void CmdHarvest(NetworkConnectionToClient sender = null)
    {
        // SphereCast forward from player for nearest tree in range
        // Lookup tree in SO Dict
        // Spawn variant
    }
jovial shard
#

ya got this so far

    void Update()
    {
        if(isLocalPlayer && Input.GetMouseButtonDown(0))
        {
            CmdSphereCast();
        }
    }

    [Command(requiresAuthority = false)]
    public void CmdSphereCast(NetworkConnectionToClient sender = null)
    {
        RaycastHit hit;

        Vector3 p1 = transform.position + sender.identity.transform.position;
 
        if (Physics.SphereCast(p1, 10, transform.forward, out hit, 10))
        {
            Vector2Int key = Vector2Int.FloorToInt(hit.transform.position);
            NetworkServer.Spawn(TreeSystem.Instance.resourceDictionary.resources[key].networkVariant);
        }
    }
wind gust
#

looks right

jovial shard
#

just that im not toggling the thign anywhere yet

#

oh nvm

#

i do, in the onstartclient

#

well eh, lets test !

#

hmm

#

Disconnecting connId=0 to prevent exploits from an Exception in MessageHandler: KeyNotFoundException The given key '(3, 0)' was not present in the dictionary.

#

line 43
Vector2Int key = Vector2Int.FloorToInt(hit.transform.position); NetworkServer.Spawn(TreeSystem.Instance.resourceDictionary.resources[key].networkVariant);

wind gust
#

layerMask, and check for having the <Tree> component, and do TryGetValue for the lookup

#

log the object it hits

#

you probably hit the terrain

#

or yourself

jovial shard
#

ah probably either yeah, ill add the layer mask

wind gust
#

make the radius small, like .5

#

imagine throwing a beachball forward - what will it hit?

#

shorten the maxDistance too so player has to be reasonably close, like axe swing range

jovial shard
#

hmm i did that, nothing happens, no hit message either

#
    [Command(requiresAuthority = false)]
    public void CmdHarvest(NetworkConnectionToClient sender = null)
    {
        RaycastHit hit;

        Vector3 p1 = transform.position + sender.identity.transform.position;

        if (Physics.SphereCast(p1, .5f, transform.forward, out hit, 2, LayerMask.NameToLayer("Resource")))
        {
            Debug.Log("We hit: " + hit.transform.name);
            Vector2Int key = Vector2Int.FloorToInt(hit.transform.position);
            Debug.Log(key);
            NetworkServer.Spawn(TreeSystem.Instance.resourceDictionary.resources[key].networkVariant);
        }
    }
wind gust
#

invert the layermask

jovial shard
#

mhm? ๐Ÿ‘€

wind gust
#

mask is what to avoid - inverted is what to hit

jovial shard
#

no way

wind gust
#

put tilde in front of it

#

~LayerMask.NameToLayer("Resource")

jovial shard
#

aaaah i added a - in there

wind gust
#

use tilde instead of hyphen

jovial shard
#

alrighty ๐Ÿ˜„

wind gust
#

or use GetMask instead

#

LayerMask mask = LayerMask.GetMask("Resource");

jovial shard
#

hmm yeah, but still no hits

wind gust
#

hmmm

jovial shard
#

i think i am hitting the capsule

#

i added some debugs

wind gust
#

player wouldn't be on that layer

jovial shard
#

true

#

then i guess the sphere isnt infront of the player Think

wind gust
#

show your current code

jovial shard
#
    void Update()
    {
        if(isLocalPlayer && Input.GetKeyUp(KeyCode.H))
        {
            Debug.Log("Hit harvest key");
            CmdHarvest();
        }
    }

    [Command(requiresAuthority = false)]
    public void CmdHarvest(NetworkConnectionToClient sender = null)
    {
        Debug.Log("I am trying to harvest!");
        RaycastHit hit;

        Vector3 p1 = transform.position + sender.identity.transform.position;

        if (Physics.SphereCast(p1, .5f, transform.forward, out hit, 2, LayerMask.GetMask("Resource")))
        {
            Debug.Log("We hit: " + hit.transform.name);
            Vector2Int key = Vector2Int.FloorToInt(hit.transform.position);
            Debug.Log(key);
            NetworkServer.Spawn(TreeSystem.Instance.resourceDictionary.resources[key].networkVariant);
        }
    }

#

is it the p1?

wind gust
#

wait...that code is on the player, right?

jovial shard
#

yes sir

wind gust
#

ok my bad - revising....

#
    [Command]
    public void CmdHarvest()
    {
        Debug.Log("I am trying to harvest!");
        if (Physics.SphereCast(transform.position, .5f, transform.forward, out RaycastHit hit, 2, LayerMask.GetMask("Resource")))
        {
            Debug.Log("We hit: " + hit.transform.name);
            Vector2Int key = Vector2Int.FloorToInt(hit.transform.position);
            Debug.Log(key);
            if (TreeSystem.Instance.resourceDictionary.resources.TryGetValue(key, out CustomResource custRes))
                NetworkServer.Spawn(Instantiate(custRes.networkVariant, custRes.position, custRes.rotation));
        }
    }
jovial shard
#

did i actually forget that Instantiate in the spawn? ๐Ÿ˜ฎ

wind gust
#

ya ๐Ÿ™‚

jovial shard
#

aye :/

#

lets see what happens with this code

#

uh oh

#

i think i know why the interact doesnt work

#

on 0,0 is the playerroot. with the interact script

#

and the player is on the left

wind gust
#

what the... ?

jovial shard
#

yeah my player doesnt move its origin

wind gust
#

oh that's gonna really make your game hard to manage

jovial shard
#

i had to do that because of gaia and their way of making the character ๐Ÿ™ƒ

#

oh tell me about it, i hate it

wind gust
#

You lose all interest management and a bunch of other things with that

jovial shard
#

PlayerCapsule is the thing that actually moves

#

๐Ÿ™ƒ

wind gust
#

oh dear lord

#

why???

jovial shard
#

ยฏ_(ใƒ„)_/ยฏ

#

thats Gaia and unity starter assets for ya

#

it used to be out there in the world

wind gust
#

That's insane

jovial shard
#

well

#

it used to be without the Player root object

#

but i added that to get a network identity on it

#

maybe i have to break it up again

wind gust
#

yeah get back to a player root that moves

#

Capsule can be a child, but move the root

jovial shard
#

i stripped it like this

wind gust
#

I do capsule as child in examples, that's fine

#

personally I'd ditch the cameras too

jovial shard
#

mhm

#

need to have eyes

#

๐Ÿ‘€

wind gust
#

have them in the scene and grab them in OnStartLocalPlayer (as seen in examples)

jovial shard
wind gust
#

search for PlayerCamera script

jovial shard
#

script on my player alone

wind gust
#

yeah you can do that too

jovial shard
wind gust
#

btw NetworkBehaviours can self-Enable in OnStartLocalPlayer

jovial shard
#

oh? thats good to know ๐Ÿ˜ฎ

wind gust
#

Anyway - are you back to moving root player object?

jovial shard
#

i have to make 1 change and then yes ๐Ÿ™‚

#

since that the cameras are not a child anymore, they dont move

#

i see the player moving but the cameras just float in the air static lol

#

maybe i can make em a children of the player root

#

oh nvm i see why lol

#

there we go1!

#

I dont see a network tree though

#

i have to register the tree in the manager. jesus

wind gust
#

yeah all the networked variants

jovial shard
#

ya

#

hmm

#

still didnt swap it out tho

wind gust
#

what'd it do?

jovial shard
#

nothing, only those debug logs

wind gust
#

what's that last log mean? 5,0

jovial shard
#

thats the key

#

the vector2int key

wind gust
#

log resources.count too

#

add an else to the TryGetValue if to iterate resources and spit out what it has

jovial shard
#

Theres 8 count. (while theres only 6 trees lol)

#

weirdly some have a null networkVariant, while i did assign them

#

this is all that comes out

#

7 is the count now,

#

the Blue to blue line (including the red ones) is the debug from the
TryGetValue else statement

wind gust
#

show code

jovial shard
#

Edit:

They are all from the else statement

#
    [Command(requiresAuthority = false)]
    public void CmdHarvest(NetworkConnectionToClient sender = null)
    {
        Debug.Log("I am trying to harvest!");
        RaycastHit hit;

        if (Physics.SphereCast(transform.position, .5f, transform.forward, out hit, 2, LayerMask.GetMask("Resource")))
        {
            Vector2Int key = Vector2Int.FloorToInt(hit.transform.position);
            Debug.Log(TreeSystem.Instance.resourceDictionary.resources.Count);
            if (TreeSystem.Instance.resourceDictionary.resources.TryGetValue(key, out CustomResource custRes))
                NetworkServer.Spawn(Instantiate(custRes.networkVariant, custRes.position, custRes.rotation));
            else
            {
                foreach (CustomResource cr in TreeSystem.Instance.resourceDictionary.resources.Values)
                {
                    Debug.Log("<color=blue>==================================================</color>");
                    Debug.Log("Treeref: " + cr.treeRef);
                    Debug.Log("<color=red>==================================================</color>");
                    Debug.Log("NetworkVariant: " + cr.networkVariant);
                    Debug.Log("<color=red>==================================================</color>");
                    Debug.Log("Position: " + cr.position);
                    Debug.Log("<color=red>==================================================</color>");
                    Debug.Log("Rotation: " + cr.rotation);
                    Debug.Log("<color=blue>==================================================</color>");

                }
            }
        }
    }

wind gust
#
foreach (KeyValuePair<Vector2Int, CustomResource> kvp in TreeSystem.Instance.resourceDictionary.resources
    Debug.Log($"{kvp.Key} {kvp.Value.position} {kvp.Value.rotaiton.eulerAngles} {kvp.Value.networkVariant}", kvp.Value.TreeRef.gameObject);
jovial shard
#

that might be nicer.

wind gust
#

That'll be easier to read, and will let you click the log entry to auto-select the object

jovial shard
#

the result!

#

theres one odd one

wind gust
#

-295 - you have something off the map someplace ๐Ÿ™‚

jovial shard
#

well thats what i thought

#

theres literally nothing in my scene

wind gust
#

it may be one that was there at one point, and has been removed but the SO dict still has it

jovial shard
#

mhm

wind gust
#

worry about finding the lookup - cleanup can come later

jovial shard
#

true

wind gust
#

ok so nothing is at 5,0 (the key you got in the SphereCast)

jovial shard
#

indeed, i never even come in that true statement

wind gust
#

did you move any trees during this process?

jovial shard
#

nope... all on the same spot

#

i created a new tree from one of these to be the network variant tho

wind gust
#

updated this

foreach (KeyValuePair<Vector2Int, CustomResource> kvp in TreeSystem.Instance.resourceDictionary.resources
    Debug.Log($"{kvp.Key} {kvp.Value.position} {kvp.Value.rotaiton.eulerAngles} {kvp.Value.networkVariant}", kvp.Value.TreeRef.gameObject);
#

key 5,0 would be 5m to right of corner and right on the edge - how'd it ever come up with that zero?

#

@jovial shard

jovial shard
#

Let's see

#

7 is count
(5,0) is key

wind gust
#

I assume the one at 5,7 is the one you hit...clicking that log entry should select that tree in the scene

jovial shard
#

now i hit (7,0)

#

which is that tree, on (7,3)

#

maybe its the issue about inputting vector3 into a vector2int?

wind gust
#

wait - you didn't make the children on same layer as root, did you?

jovial shard
#

Sorry, what do you mean with that exactly? ๐Ÿ˜ฎ

#

oh

#

yes i did

#

from the tree

#

they all 3 (lods) have the same layer

wind gust
jovial shard
#

ya..

#

all the same

wind gust
#

only the roots should be on Resource layer - check the children

jovial shard
#

o

wind gust
#

put them back to Default if they're not

#

or....

#

let all children be on Resource layer, but drill up to transform.root.position for the key

jovial shard
#

i changed trhem all to default, and the roots are now Resource

#

and yet, still a (5,0)

#

not (5,7)

#

maybe it doesnt like this Vector2Int.FloorToInt(hit.transform.position);

#

maybe it takes the X and Y

#

not the X and Z

wind gust
#

try Vector2Int key = Vector2Int.FloorToInt(hit.transform.root.position);

jovial shard
#

still 5,0

wind gust
#

Vector2Int.FloorToInt(hit.transform.position); is what you used to put them in the dict so same function to find them

jovial shard
#

not really

#

i did this in the onvalidate Vector2Int key = Vector2Int.FloorToInt(new Vector2(transform.position.x, transform.position.z));

#

explicitly say x and z

wind gust
#

ohhh

jovial shard
#

๐Ÿ‘€

wind gust
#

I thought you did the other

jovial shard
#

nah only for this one ๐Ÿ˜„

wind gust
jovial shard
#

yeah thats on the onstartclient

wind gust
#

ooof

jovial shard
#
    private void OnValidate()
    {
        //Add to treesystem
        Vector2Int key = Vector2Int.FloorToInt(new Vector2(transform.position.x, transform.position.z));
        FindObjectOfType<TreeSystem>().resourceDictionary.resources[key] = new CustomResource { treeRef = this, position = transform.position, rotation = transform.rotation, networkVariant = networkVariant };
        Debug.Log(FindObjectOfType<TreeSystem>().resourceDictionary.resources.Count);
    }
wind gust
#

ok

jovial shard
#

onvalidate is different again pepeHihi

wind gust
#

ok then it's ignoring Z which won't work for us

#

use explicit x, z in all cases

jovial shard
#

alright :D!

wind gust
#

and put all children on Resources layer so you have a better chance of hitting a branch with the spherecast, and transform.root.pos to get the key

jovial shard
#

so the parent NOT on the resources layer?

wind gust
#

It should've occurred to me that Vector2 is for 2D so z would be the axis it ignores

#

parent and children on Resource layer

#

so it won't matter which part of the tree you hit

jovial shard
#

got it

wind gust
#

otherwise it could be too hard for player to hit just the trunk

jovial shard
#

just going on about

#

transform.root.pos to get the key

#

which part would that be to change ๐Ÿ˜ฎ

wind gust
#

in the spherecast

        if (Physics.SphereCast(transform.position, .5f, transform.forward, out hit, 2, LayerMask.GetMask("Resource")))
        {
            Vector2Int key = Vector2Int.FloorToInt(new Vector2(transform.root.position.x, transform.root.position.z));
#

Since I don't know where all the colliders are in a tree's hierarchy

jovial shard
#

so this Vector2Int key = Vector2Int.FloorToInt(new Vector2(transform.root.position.x, transform.root.position.z));

#

okay

#

it saYS

#

5,6 now

#

but the tree is at 5,7 ๐Ÿ‘€

wind gust
#

lol

jovial shard
#

xD

wind gust
#

actual pos is...?

jovial shard
#

Tree actual pos is x 5.64
Indicated HIT pos is (5,6)
actually read pos by the script from the tree is (5,7)

#

im doing floortoint

wind gust
#

z?

jovial shard
#

sorry

#

that was x

wind gust
#

the x is right, the z is wrong

jovial shard
#

tree actual pos = 7.249999
HIT pos = (5,6)
indicated tree pos = (5,7)

#

the hit pos is wrong

wind gust
#

ohhh

        if (Physics.SphereCast(transform.position, .5f, transform.forward, out hit, 2, LayerMask.GetMask("Resource")))
        {
            Vector2Int key = Vector2Int.FloorToInt(new Vector2(hit.transform.root.position.x, hit.transform.root.position.z));
#

hit.

jovial shard
#

oh myt god

#

its taking the player pos

wind gust
#

without hit. you're pulling the player's pos

jovial shard
wind gust
#

hehehe

#

it's the little details...always

jovial shard
#

Okay! the tree spawned in

wind gust
#

yay?

jovial shard
#

didnt deactivate the old tree though

#

thats onto here
public override void OnStartClient() { Vector2Int key = Vector2Int.FloorToInt(new Vector2(transform.position.x, transform.position.z)); CustomResource tree = TreeSystem.Instance.resourceDictionary.resources[key]; tree.treeRef.ShowHide(true); }

wind gust
#

no warnings / errors?

jovial shard
#

nope, all looks normal Think

#

addded a debug log to the startclient

#

to see if it actually runs

#

it does run

#

maybe this is wrong lol

#
    public void ShowHide(bool active)
    {
        gameObject.SetActive(active);
    }
#

(im passing it a true / false)

wind gust
#

gameObject.SetActive(!active);

jovial shard
#

o

#

i just noticed

#

im setting them active when the tree spawns

wind gust
#

or pass false from OnStartClient

#

and true from OnStopClient

jovial shard
#

this works ๐Ÿ˜„

#

got a network tree

#

and the other tree gone

#

didnt even notice them changing

wind gust
#

๐Ÿ™‚

jovial shard
#

damn! awesome ๐Ÿ˜„

wind gust
#

now you can destroy the networked tree from server after some time and the original should come back

jovial shard
#

aww yeah ๐Ÿ˜„

#

Is the NetworkedTree.cs also the place where i can keep track of hits, tree damage, drops etc?

wind gust
#

hint - Destroy(gameObject, 300); works for networked objects (300 = 5 minutes)

jovial shard
#

oh PeepoHappy

wind gust
#

you can put that right after your NetworkServer.Spawn

#

so it will self-destruct after whatever time you put

jovial shard
#

alright pepeHihi

wind gust
#

can't remember if that's seconds or ms

#

probably seconds

jovial shard
#

will see that, no probs ^_^

jovial shard
#

Awesome!

#

huge stuff right here

#

because this is the base for ALL resources

wind gust
#

you can add disabled damage art to the networked variant and enable it on client as its health is reduced

jovial shard
#

๐Ÿ˜„

#

i like that

wind gust
#

Health SyncVar with hook to show that

jovial shard
#

gotcha ๐Ÿ™‚

wind gust
#

can add a kinematic Rigidbody to it and nudge it with some angularVelocity to knock it over

jovial shard
#

thats some good struff to do ๐Ÿ˜„

wind gust
#

then on server you can add firewood or lumber to player's inventory

#

or spawn that on ground for player to pick up

jovial shard
#

i like that ๐Ÿ˜„ i have been trying to make an inventory system for a while but cant get the hang of it lol, but its fine, stuff for another time ๐Ÿ˜Š

wind gust
#

so after cleaning up logging and such, tidying up the code...what all did you end up with in the various parts? put it all in pastie.io for me?

jovial shard
#

sure hold up

wind gust
jovial shard
wind gust
#

I figure I've put the time into this today - may as well make a doc out of it.

jovial shard
#

hahaha right ! let me paste it together for you

wind gust
#

oh, and if/when you get close to a public release, SO's are assets and can be shipped as Addressables / Asset bundles

jovial shard
#

added a bit of explanation to some of the scripts

#

its actually not even that much code, holy evil

wind gust
#

we simplified this

    [Command(requiresAuthority = false)]
    public void CmdHarvest(NetworkConnectionToClient sender = null)
jovial shard
#

shees did we

#

๐Ÿ˜ฎ

#

oh yes

jovial shard
#

yeah ๐Ÿ˜„

wind gust
#

fix this

    public override void OnStopClient() {
        Vector2Int key = Vector2Int.FloorToInt(transform.position);
jovial shard
#

oh! i skipped one!

#

fixed ๐Ÿ˜„

wind gust
jovial shard
#

one sec ๐Ÿ™‚

#

oh sorry i was on org

wind gust
#

out Raycast hit eliminates having to declare it separately

jovial shard
#

๐Ÿ‘€

#

hehe

wind gust
#

probably should cache the key from OnStartClient in case the thing moves via damage / falling over, etc. and use the cached value in OnStopClient

wind gust
jovial shard
#

i did in my actual code, woops haha

#

theres still a debug line in there

wind gust
#

I'd suggest taking the ! out of this and flipping the true and false in the callers
gameObject.SetActive(!active);

#

less confusing

jovial shard
#

true ๐Ÿ˜Š

#

this should be the correct pastie then ๐Ÿ˜„

#

if you make that into a doc, that might help so much people that are stuck on this issue ๐Ÿ˜ฎ

wind gust
#

you still need to flip the true / false in the callers

jovial shard
#

its literally the base for all things resources

wind gust
#

now the only thing to add is when you move trees, they'll add themselves again at a new pos, so need a mechanism to clear the dict and re-run the validation

jovial shard
#

yes...

#

i mean

wind gust
#

or when removing them

jovial shard
#

in the onvalidate cant i clear first and then add?

#

oh nvm, it would clear previously added ones

#

woops

wind gust
#

TreeSystem.cs...

[ContextMenu("Clear Resources")]
public void ClearResources()
{
    resourceDictionary.Clear()
}
jovial shard
#

yeah i mean, why not

#

a neat hidden clear option

wind gust
#

looking for something to call OnValidate on everything...reloading the scene might work

#

try it and see?

jovial shard
#

(saving a script that builds also onvalidates everything again)

wind gust
#

k

jovial shard
#

and reloading scene too ๐Ÿ™‚

wind gust
#

What does Odin show for it now?

jovial shard
#

it doesnt show anything

#

i think i didnt add the right header to it

wind gust
#

select the asset itself

jovial shard
#

๐Ÿ˜›

wind gust
#

maybe needs an odin attribute, right

jovial shard
#

let me check

wind gust
#

CustomResource struct probably needs [Serializable]

jovial shard
#

valid poiint

wind gust
#

just something to at least show the count, if not all the entries

jovial shard
#

oh, Odin doesnt support dictionary serializing

#

only lists etc

wind gust
#

oh well - as I said - don't get bogged down in that

jovial shard
#

indeed

#

But the entries is 6

#

and i have 6 trees

#

which means, the cleaning works

#

since i had 7 before

wind gust
#

so clear worked and they re-validated

jovial shard
#

yeah ๐Ÿ˜„

wind gust
#

good

jovial shard
#

amazing ๐Ÿ˜„

wind gust
#
[ContextMenu("List Resources")]
public void ListResources()
{
    foreach (KeyValuePair<Vector2Int, CustomResource> kvp in resourceDictionary.resources
        Debug.Log($"{kvp.Key} {kvp.Value.position} {kvp.Value.rotaiton.eulerAngles} {kvp.Value.networkVariant}", kvp.Value.TreeRef.gameObject);
}
jovial shard
#

added that too ^^

wind gust
#

fixed ^ (resourceDictionary)

jovial shard
#

almost fixed ๐Ÿ˜‰

#

resourceDictionary.resources

#

๐Ÿ˜›

#

resourceDictionary is the script, resources is the actual dictionary in that script pepeHihi

wind gust
#
TreeSystem.cs (Tree system, an actual in world object with NetworkBehaviour on it)
 
public ResourcesDictionary resourceDictionary;
#

ohh

#

right

jovial shard
#

๐Ÿ˜„

wind gust
#

details details ๐Ÿ˜›

jovial shard
#

true true ๐Ÿ˜„

wind gust
jovial shard
#

Yesss ๐Ÿฆพ

wind gust
#

nice solution - not much code, pretty easy to understand

jovial shard
#

indeed, felt like alot more work flushed

wind gust
#

Harvesting in ~60 lines of code - not bad ๐Ÿ™‚

jovial shard
#

Exactly ๐Ÿ˜„

#

perfect for noobs ๐Ÿ˜ฎ

wind gust
#

it's not a one-click done, but should be good enough to swallow for most people

jovial shard
#

exactly ๐Ÿ˜„ and you can use it for more resources ๐Ÿ˜„

#

not only resources

wind gust
#

What other applications would you think?

jovial shard
#

Well, this has basically every sign of; If you need something interactive networkwise, but dont want it to be alive all the time, only on instances. For example, a ball with physics etc. Only when the player touches it, it switches out for a network variant, and after that it hasnt been touched for a while it can go back to the ''local variant ''

wind gust
#

can't be anything that moves

jovial shard
#

maybe even posible for animals, although you want to see them both on the same spot for 2 players

#

hmm

#

i guess true!

#

since were locked to the key

wind gust
#

The location key requires it to not move

jovial shard
#

yeah, maybe people can find another key to use for it ๐Ÿ˜Š

#

create a custom key

#

attach an id to the ball

wind gust
#

GUID in tree.cs

jovial shard
#

exactly

wind gust
#

I can't remember if VegetationStudio lets you put MonoB's on things it's generating at runtime

jovial shard
#

not sure either,
i just know that Gaia and GeNa do nothing on network parts. So thats all for the customers of them to figure out themself

#

sounds like a huge W in the books if we get that on the Mirror Docs

wind gust
#

side note - how big is your scene (terrain)?

jovial shard
#

well the one im working at is a normal terrain from unity 1x1x1, let me go look at the terrain from gaia (which i will use after i got all the stuff done and working)

#

atm its a 1x1x1 unity terrain

1,02 km x 1,02 km

#

not too big

wind gust
#

so 1024 x 1024 ?

jovial shard
#

yeah or that xD

wind gust
#

that small won't matter, but if you go big, center it over 0,0,0, e.g. pos at -512, 0, -512

jovial shard
#

i saw that the terrain was at -512,0,-512

wind gust
#

and have the game work out from center, so the edges far from origin are basically unreachable by topography

jovial shard
#

mhmm

#

i see ๐Ÿ˜„

wind gust
#

steep cliffs or water or something

#

or just trees so thick they can't get through them

jovial shard
#

theres alot of water, that part is still being worked on on how to keep the players on ๐Ÿ˜›

wind gust
#

A project I've been messing with has 18K x 18K area cut into 2Kx2K terrain scenes

jovial shard
#

๐Ÿ˜ฎ ๐Ÿ‘€

#

my unity keeps spazzing out already on 1km, every click i do just opens up a stupid progressbar

#

waits for 40 sec and then is done lol

wind gust
#

need better hardware lol

jovial shard
#

man i thought i was on some goood stuff

#

๐Ÿ™ƒ

#

NVMe
2060RTX
32GB ram
AMD Ryzen 7 3700X

#

welp

#

can always be better tho haha

wind gust
#

This is why I have them in subscenes - only have a couple loaded at a time

jovial shard
#

i see, but you use veg studio?

wind gust
#

haven't recently, but yes that's the terrain engine

jovial shard
#

hmm, i havent found the option in GAIA yet to split into scenes

wind gust
#

I think you need Sectr to do that

jovial shard
#

ah yes

#

throw in another โ‚ฌ100

wind gust
#

It's been almost a year since I've had time to mess with this stuff, and with summer coming it'll be another 8 mos before I can get back into it

jovial shard
#

oh? How come another 8 months ๐Ÿ˜ฎ

wind gust
#

summer gets me outdoors more

jovial shard
#

i see, fair enough ๐Ÿ˜‰

wind gust
#

I do my best work in winter when I'm shut in

jovial shard
#

yeah, makes me not feel bad sitting inside too xD

wind gust
#

and i've got 2 mos of winter left, and too much on my plate to work on that game now

jovial shard
#

aye i see

#

and yet you took time off to help me with this pretty important feature for MY game ๐Ÿ˜Š

wind gust
wind gust
jovial shard
#

iknow right! ๐Ÿ˜„

#

AND it gets a feature on the docs to help others out

#

amazing ๐Ÿ˜„

wind gust
#

will do the doc later - need food

jovial shard
#

You do that ^^ enjoy the meal

wind gust
#

go make an inventory or something lol ๐Ÿ˜„

jovial shard
#

yeah i will! ๐Ÿ˜„ Thanks for the help, awesome man so excited ๐Ÿ˜›

wind gust
#

np ๐Ÿ™‚

jovial shard
#

oof ๐Ÿ˜Š

wind gust
jovial shard
#

the amount of messages haha

wind gust
#

ohh lol

jovial shard
#

๐Ÿ˜Š

wind gust
jovial shard
#

yeah....... i guess you win

wind gust
#

pretty much lol

jovial shard
#

haha ๐Ÿ˜„

#

backbone of the community

wind gust
#

ty ๐Ÿ™‚

jovial shard
#

๐Ÿ˜„

jovial shard
#

In the docs, where will you be putting this under? ๐Ÿ˜Š

wind gust