Finding the Joint from the Connected Body - c#

I'm wondering if it's somehow possible to find the Joint that holds my Rigidbody, through the rigidbody?
Allow me to clarify more
I have my GameObject and it has a FixedJoint which has a Rigidbody attached to it (the connectedBody) and what I want to do is to find the FixedJoint, by looking for it from the Rigidbody.
Reason to why I want to do this is because I want my Joint to break when my Rigidbody hits something hard enough. I can't use BreakForce as it's checked all the time, so if I turn my original object fast enough it will break.

Through the Rigidbody, unfortunately there isn't. Given the FixedJoint, you can check its connectedBody property, but you can't check it the other way around.
Don't forget, though, that you can always attach a custom component.
Something like this would be simple enough:
public class FixedJointConnection : MonoBehaviour {
public FixedJoint joint;
}
When you attach the joint, you can also attach a FixedJointConnection and set the joint reference.
You can even write a helper function to do just that:
public static FixedJointConnection Connect(Rigidbody anchor, Rigidbody child) {
FixedJoint joint = child.AddComponent<FixedJoint>();
joint.connectedBody = anchor;
joint.connectedAnchor = anchor.transform.InverseTransformPoint(child.transform.position);
//TODO: any more joint config? depends on your game
FixedJointConnection connection = anchor.AddComponent<FixedJointConnection>();
connection.joint = joint;
return connection;
}
From there, you can add a check during each collision:
Do we have any FixedJointConnection(s) attached?
If so, did we hit hard enough to break them?
Depending on what exactly you need, your custom component class can be very simple or fairly complex. Doesn't matter, though; the point here is just that Unity's components provide powerful features, and that you can amplify those features by writing your own.

Related

Spawning gameobjects relative to the position, width and length of another gameobject?

I'm currently developing a game in Unity using C# and I've run into a small problem.
I need to spawn a certain gameobjects relative to the Spawnposition and length of another game object. Now I figured that bounds.size would be the best function to use in this instance. As shown bellow I declare first the variable that uses this in my start method:
public void Start()
{
GameObject PointBar = (GameObject) Resources.Load("PointBar Horizontal");
PointBarVectorLength = PointBar.GetComponent<BoxCollider2D>().bounds.size.x;
PointBarVectorConv = Camera.main.WorldToViewportPoint(new Vector2(PointBarVectorLength, 0f));
}
However, the gameobjects in question are inactive at start's call and thus I presume don't return any value for bounds.size when called.
Does anyone know how I can access the bounds.size or equivalent of an inactive gameobject or is there something else I'm missing here?
As noted in the documentation for the Collider.bounds property, bounds "will be an empty bounding box if the collider is disabled or the game object is inactive". So your assumption was pretty much right. Since the object doesn't exist in worldspace that makes sense.
I'm not sure about the most elegant solution for your use case but two options spring to mind.
Calculate the object's spawn dimensions by accessing its transform.localScale and factoring in the scale of prospective parent objects. That could get messy but you could probably also write a helper method to make it more manageable.
Instantiate the object somewhere off screen after you load it, access its Collider.bounds property to get the information you need then move it where ever you want it or store the information for later.
There may be better solutions but that's what leaps to mind for me.
I solved the issue by using GetComponent().bounds.size.x;
instead of BoxCollider. This component can get accessed when the game object is not active.

How to make a trigger only for one of objects?

I have a car in my game with 4 wheels(Unity3D):
Also i have a trigger of EndLevel:
But after when im going throght the trigger its trying to work 4th times
How can i change it?
I tried to add my "Player(car)" inside EndGame object but its didnt fix my problem.
using UnityEngine;
public class EndTrigger : MonoBehaviour
{
public GameManager gameManager;
void OnTriggerEnter()
{
gameManager.CompleteLevel();
}
}
First of all note that OnTriggerEnter(Collider other) requires a parameter of type Collider otherwise it wouldn't get called at all.
Flag
The simplest solution might be adding a bool flag as already mentioned by Eric Warburton's answer.
Layers
I would prefer to rather tackle the origin of the issue and suggest using different Layers and then configure the Layer-based collision detection via the Edit&rightarrow;ProjectSettings&rightarrow;Physics&rightarrow; Layer Collision Matrix.
Create a Layer e.g. END and assign it to your goal collider object. Make this object not Is Trigger and rather attach your script checking for OnTriggerEnter here.
Create a Layer e.g. Player create a new dedicated invisible object with a collider and enable Is Trigger here. This object has the only purpose of colliding with the goal collider nothing else. Assign the Player layer here.
Configure the collision matrix thus that END only collides with Player and nothing else. And Player only collides with END and nothing else - or maybe later another effect layer like e.g. PowerUps ;)
You can create up to 24 custom layers and make use of the already existing ones so this should hold up a while
Tags
Another alternative to the Layers is using Tags
As previously I would make the END object not a trigger but rather use one on the Player.
Then you can simply compare the tag using CompareTag
void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Player")) return;
gameManager.CompleteLevel();
}
in very very complex games this might be sometimes better since you can create a lot more Tags than Layers.
Well there are a few things that I can think of trying.
You can make sure that only one of your colliders is a trigger. There should be a bool check in the properties to uncheck for your wheels.
You can also do something like creating a counter or a bool that prevents the OnTriggerEnter() from firing multiple times if you only want it to fire once. You can reset it at the start of levels if needs be.
Something like
void OnTriggerEnter()
{
if (!gameManager.IsLevelComplete)
gameManager.CompleteLevel();
}
Inside the gameManager script
public bool IsLevelComplete { get; set; }
public void CompleteLevel()
{
IsLevelComplete = true;
//Do stuff
}

Why are transforms typically passed when working with in-game objects rather than game objects?

I am well along in learning Unity basics but would like to nail down my understanding of the relation between components and the objects that own them. In the tutorials I've been watching typically use or pass the Transform component when working with objects pulled in code. For example:
void Explode ()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRadius);
foreach (Collider collider in colliders)
{
if (collider.tag == "Enemy")
{
Damage(collider.transform);
}
}
}
which calls "Damage" with the transform on the colliders it finds:
void Damage (Transform enemy)
{
Enemy e = enemy.GetComponent<Enemy>();
if (e != null)
{
e.TakeDamage(damage);
}
}
Looking at this, it is clear that it is pulling a Component found on all game objects and then using "GetComponent" to pull another component instance by name since the "Enemy" component isn't going to have its own method. Why not just pass collider.gameObject though? I tried this (after changing the Damage to expect a GameObject) and it worked fine.
This seems more intuitive to me but all of the tutorials I've seen use the transform component instead. Does anyone have any insight into why this is so? It would help me deepen my understanding of how Unity structures its code.
I'm not sure what tutorials you are following, but the ones I followed when I first started with Unity used GameObject instead of Transform.
I agree that it is more intuitive to use GameObject. Transform is a part or Component of a GameObject, but since it's mandatory it will always be there, hence the public field .transform. But since a GameObject is technically the holder of all its Componenents, it would be most logical, architecture wise, to pass that as a parameter instead.
At the end of the day, it makes little difference in your examples since you can call a lot of the same methods on both Transform as GameObject.
TLDR:
Use whatever you feel makes most sense.
Short answer
GameObject is more intuitive as you say.
Long answer
I think (my opinion) it's best to pass the most specific and relevant component.
For example, assume you have a function for a character to pick up a crate:
public void PickUp(Transform crate)
{
crate.SetParent(this.transform);
crate.localPosition = Vector3.zero; // or whatever your attachment point is
}
Here it makes sense in my mind that the Transform is passed, because it's the most specific component that will be needed.By passing GameObject here you are only delaying the inevitable GetComponent<Transform> or go.transform.
On the other hand, if you have a function to hide a create then passing the game object would be the bare minimum you need to achieve this:
public void Hide(GameObject crate)
{
crate.SetActive(false);
}
Passing anything else just delays the inevitable x.gameObject
In the explosion example I don't think that I would pass either to be honest. I would probably do this:
void Explode ()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRadius);
var enemies = colliders
.Select(x => x.GetComponent<Enemy>())
.OfType<Enemy>(); // Or IHealth, IDamageable, ITarget, etc if you have other things that can take damage.
foreach (var enemy in enemies) // If empty, nothing will happen by default
{
enemy.TakeDamage(damage);
}
}
With this approach you can see that there is no need to check tags or nulls. The enemies enumerable is guaranteed to contain either enemies or nothing at all.
By always passing gameObject/transforms you will always have to worry about what it is that you are really receiving at the destination component. You will also open yourself to situations where you are not sure anymore where certain changes to you gameObjects are being made because it can be anything in the system that's making those changes. Your ColorChangerComponent could actually also be moving the object around, destroying some other components, etc. By giving the component a Renderer, it more naturally limits the component to changes on the Renderer only (although you could obviously violate this limitation unless you perform actions against appropriate interfaces).
The only time it really makes sense to pass a generic component is when you are broadcasting this 'event' to a bunch of possible receivers that will each to a different thing with the object. I.e. you can't be certain at compile time what the gameobject will be used for, or you know that it will be used for many different things.
The fact that Unity itself returns Collider[] for the collision check sort of supports this line of thinking, otherwise it would've just returns GameObject[]. The same goes for OnTriggerEnter(Collider collider) or OnCollisionEnter(Collision collision) etc.

Emitting a constant force from an object(Leaf blower Mechanic) C#

I am just about to tackle a new project where the core game mechanic is covering up dead bodies killed by the mafia with leaves using a leafblower.
You need to cover them well enough to not draw attention when the police question you.
The only problem I can see with this project is how to create this leafblower mechanic.
Off the top of my head I can think of attaching an empty object to my leaf blower which has a constant [rigibody.AddExplosiveForce] that procs on mouse click but thats it.
What should I be looking at and what would be a logical way to create this? You do not need to write the whole code for me, I just wan't to know what tools or scripting API I need to consider.
Thank you :)
You could try continuous adding force using Rigidbody.AddForceAtPosition(). Or calculate directions and try Rigidbody.AddForce().
Basically Rigidbody.AddExplosionForce is working as Rigidbody.AddForce, but uses sphere to calculate Vector3. If you need to emit it continuously, you should just use it in FixedUpdate() and list of object you can get by using Raycasts or simple Trigger Collider, for example Capsule Collider.
You could use Collider Capsule like this ↑↑↑. And in OnTriggerEnter or OnCollisionEnter:
private void OnCollisionEnter(Collider other) {
if (other.gameobject.tag != "leaf") return;
// Your AddForce here.
// Also you can get exact point of collsion by using
// other.contacts and use this as AddForce argument.
}

Character Controller For C# Need transform.translate to collide, not teleport

I am fairly new to code, I know some of the basics but my knowledge is limited, so please let me know WHY in your answer if it's not too hard to explain, I'd like to learn rather than just be given the answer!
This code is the basic controls for a game i am making. I'll be explaining the premise of the game just so you're able to better grasp what my intent is.
The game will focus on the completion of mazes, however movement is restricted to only being able to go forward, and right. You may never do a u-turn, go left or go backwards.
With my current code, it is possible (VERY EASILY POSSIBLE) to just translate over the entire maze and the colliders for walls don't apply due to it being a translate, which to my understanding is essentially 'teleporting' it.
I've looked around on similar topics and discussions but I was unable to find any answers that addressed this kind of issue with colliders.
When the object collides with a 'wall' in my maze, I want the object to be reset to it's original position, or at the very least die, I'm not sure if that will affect the answer given, but just incase keep that in mind, thank you!
using UnityEngine;
using System.Collections;
public class Movement_Script : MonoBehaviour {
public float playerspeed = 1;
void Update () {
if(Input.GetKeyDown("up"))
{
transform.Translate(Vector3.up * 1);
}
if(Input.GetKeyDown("right"))
{
transform.Translate(Vector3.right * 1);
transform.Rotate(Time.deltaTime,0 ,-90);
}
}
}
When you control the transform, you are telling "Place this there".
So when you do:
transform.Translate(Vector3.up * 1); // multiplying by one is useless
you tell to displace the object by 0,1,0 from its current position. This is regardless of any environment. You still can detect collision by it won't be resolve by the engine, you would have to do it yourself.
Unity came up with a ready to use solution with the character controller component. It does the same as you do in your code but also perform a bunch of collision checks and resolve them. The latest version is actually using rigidbody for a more physical approach.
http://docs.unity3d.com/Manual/class-CharacterController.html
http://docs.unity3d.com/ScriptReference/CharacterController.Move.html
the Move method is the one to use for Unity to handle the whole process for you. I would recommend to install a basic four wall room with a few boxes here and there so that you get the grip of it. Then it will be easy to move on to do whatever you want with it, whether 2D or 3D movement.

Categories