Generate a variable for each object that collides
Hi, im new to the forum, i logged in to ask a question... Actually Im developing a project where i need to generate and share a variable (a float) between two gameobjects, like a friendship on Sims (not so complex) or similar videogames. The problem is that after a long time I can not see a way to do it.
For now, what I have is that when the player collides with another object, it's been added to a list of "Contacts". My closer idea is to generate a variable in order for each gameobject who is in to this list. The problem is that I find no way to generate this variable.
I hope to solve this, and thanks for any help :D
Answer by Statement · Nov 10, 2015 at 09:38 PM
For both objects to access the shared relationship formed after a collision, both of them could keep a Dictionary of object/friendliness.
Dictionary<GameObject, float> friends = new Dictionary<GameObject, float>();
void OnCollisionEnter(Collision collision)
{
if (friends.Contains(collision.gameObject))
{
// I already know this dude. He's my friend. Let's be more friends.
friends[collision.gameObject] += 1f;
}
else
{
// A new dude. Dunno if I like him. Ok, yes I do.
friends[collision.gameObject] = 1f;
}
}
However this approach each friend has a connection that is private to one another. For example, the green sphere and the yellow sphere could both know each other with 3 friendliness to each other.
But, yellow can modify their friendliness to green, so yellow thinks green is 10 friendly while green thinks yellow is 3 friendly. If you want them both to share the same weight, you should let another class deal with the relationship. It's not so much of a problem if you only update the friendliness on contact because both will do the same action on each side so the effect is mirrored, but if one decides to bump up the friendliness after another action that doesn't involve the other, then the two will have different stances to one another.
Consider implementing a class that provides a simple to use, static interface such so you can do:
// Increase bond between me and the other by "2" friendliness for this event.
Friends.IncreaseBond(gameObject, collision.gameObject, 2);
// Later on, you may want to see all the bonds you have accumumated:
var bonds = Friends.GetBonds(gameObject);
foreach (var bond in bonds)
Debug.LogFormat("My bond with {0} is {1}.", bond.other.name, bond.value);
// Or just get a specific bond:
var bond = Friends.GetBond(gameObject, someOtherGameObject);
For the second solution, one should consider that you need some kind of order/sorting for the Friend class. So that Friends.IncreaseBond(gameObject, collision.gameObject, 2)
is the same as Friends.IncreaseBond(collision.gameObject, gameObject, 2)
To archive that, i would implement an dictioniary . where friendship is an object taking two gameobjects, overloading the equal operator and hashvalue.
but it might go easier.
Hey, thanks all for your answers. It worked, but i not understand how to use the second part of this (Im using C#, maybe it's for it)... I must do it on another new script or in the same?
I have tried to do it on another script, but i cannot get the collider.gameObject who collides on the other script. And .IncreaseBond or .GetBond gives me an error.
Sorry if this questions seems like a bit stupid, im not an expert.
And thanks another time for all.
The example provided is C#.
The second part, I guess you mean the Friends class idea?
You must write the class yourself. This is what I meant by "Consider implementing a class". It is up to you to create the class Friends with the methods IncreaseBond, GetBonds and GetBond if you want to have that functionality. This is only a suggestion on what you can do, not the way you must do it.
To get started, create a new .cs file called "Friends", and start typing.
I don't mean to impose onto you any design of how to implement that, but a skeleton could look like this:
using UnityEngine;
using System;
using System.Collections.Generic;
public static class Friends
{
// TODO: define data structures to store objects
public static void IncreaseBond(GameObject left, GameObject right, float bond)
{
// TODO: Write this method.
throw new NotImplementedException();
}
public static IEnumerable<Bond> GetBonds(GameObject obj)
{
// TODO: Write this function.
throw new NotImplementedException();
}
public static Bond GetBond(GameObject obj)
{
// TODO: Write this function.
throw new NotImplementedException();
}
}
public sealed class Bond
{
// TODO: Write data required to implement your needs.
//
// For example, if you can alter the value of bond,
// you may need to write back into Friends depending
// on how you decide to implement your data structures.
public GameObject other
{
get
{
// TODO: Write this propery.
throw new NotImplementedException();
}
}
public float value
{
get
{
// TODO: Write this propery.
// $$anonymous$$aybe also add a setter.
throw new NotImplementedException();
}
}
}
I think I understand it finally, thanks you again and all who have answered. I tried it and it worked, because for now i dont see any problem.
Again, thanks all :D
Or you can just glance the assets or code.
Example usage
Bond
BondAttribute
Dictionary2D
And more code that I didn't feel was necessary to get the picture. Oh, right. Picture:
Answer by Soraphis · Nov 10, 2015 at 05:13 PM
Not sure if i've got your problem but: Create a Hashtable (or Dictionary) where you save pairs
Dictionary<GameObject, float> friendship = new Dictionary<GameObject, float>();
so, you can check if one gameobject has a friendship-level to another:
friendship.ContainsKey(gameobjectA); // return boolean
you can set a value like that:
friendship[gameobjectA] = 5.1f;
and with: friendship.Keys;
you'll get a list of all gameobjects in this dictionary, and with friendshipt.Values
you'll get all the values.
Thanks for the answer. Im not and advanced user, and never used Dictionary, I suppose that it's like a List but it takes two variables. I dont know if you understand my question, as I have explained it badly (and im not english and doesnt speak so well :S). I hope with that picture i can explain my problem well:
![alt text][1] [1]: /storage/temp/57925-friendship.png
When the player collides with another gameobject, it's added to a list. What I mean is that when this object has been added to the list, generate a float variable,"friendship" ,
that is shared by these two objects , the player and the object that collided.
Thanks again for the answer, i hope solve this.
Yes, that can be done with a dictionary. A dictionary is like a C++ std::map. I don't know if that help you at all.
But basically, a dictionary lets you look up something based on a "key".
Think of the analogy of a dictionary book. You want to know what "knowledge" is, so you go to the entry of "knowledge" (this is the key) and find "acquaintance with facts, truths, or principles, as from study or investigation; general erudition" (this is the value, mapped to the key).
But ins$$anonymous$$d of looking up "meanings of words", you are looking up "friendships of objects". The relationship in Soraphis example is implemented as a real number, where higher numbers mean tighter friendship.
So like with the dictionary example, you look up "what is my relationship with the green object?", if it doesn't exist, create a relationship (add the key and default value). Soraphis example suggests that the relationship to each object can be different (different numbers).
If you don't need different relations to different objects, a HashSet or List could do as well. Ins$$anonymous$$d of storing a unique value for each relationship, you could just settle on "I know who that is", and nothing more. Then you could just add the other object into a collection such as HashSet or List and see if it contains there on contact. If not, add it there so it knows for next time.