I'm trying to drive a configurable joint to the same rotation as another game object. Basically I'm trying to get one marionette to shadow another.
Im using the following code:
public GameObject master;
public GameObject slave;
void Update (){
ConfigurableJoint cj = slave.transform.GetComponent(typeof(ConfigurableJoint)) as ConfigurableJoint;
cj.targetRotation = master.transform.rotation;
}
However, I don't get any rotation out of the slave. Can anyone explain what I should be doing?
Are you sure you are getting the right joint ? Is cj null ?
Maybe try this line instead :
ConfigurableJoint cj = slave.GetComponent<ConfigurableJoint>();
When you are dealing with physics you can't apply rotation to a Rigid Body. What you can do is copy and paste the local transform to another non-static game object in relationship with its perent that does not contain a Rigid Body.
So basically the configurable joint has so so many options and parameters to set it up to your need that you need to take a course 2hrs course. There is no space here for a simple answer to set it up. I recommend this free old course because is the only one that at the moment explains in deep: This is more a general answer but works. There is an old tutorial in Unity3 that explains the setup:
https://archive.org/details/3dbuzz-archive/unity-fundamentals-part-04/020-physics/013-13-configurable-joint.mp4
Related
I am currently working with the Hololens 2 for a project and am now trying to spawn an object at the position I target with the hand ray. First I created a mesh with the Spatial Awareness System from MRTK and now I want to spawn an object at the position of the cursor.
I read about a lot of ways I can handle this, like cursor.transform.position (which doesn't work, maybe because I use the default cursor?) and Instantiate, the component "Tap to Place", or using RaycastHit. Unfortunately, because this is my first time working with the Hololens, I don't know which solution might be the best. I don't think it can be that hard to spawn something, but maybe I am just blind.
Is there an easy way to solve my problem or get the right coordinates from the cursor of the hand gaze?
Here you go, use IMixedRealityPointerHandler. See the documentation.
public void OnPointerClicked(MixedRealityPointerEventData eventData)
{
var result = eventData.Pointer.Result;
var hitPosition = result.Details.Point;
// Check if hitting spatial mapping layer
if (result.CurrentPointerTarget?.layer == 31)
Instantiate(yourPrefab, hitPosition, yourRotation);
else
Debug.Log("Hit surface with layer: " + result.CurrentPointerTarget?.layer.ToString());
}
so I've been struggling with a problem for a while, not sure how to approach it.
I'm trying to simulate a magic system similar to The Force used in Star Wars in Unity, and have ran into some troubles. I'm trying to simulate pushing and pulling on objects appropriately. This means that when the player pushes an object, both the player and the object get a force applied to them. If the object is light enough, the player shouldn't be affected in any noticeable way, and the object should be pushed away. If their masses are similar, both should be pushed away at some rate, and if the object is heaver, the player should be mainly pushed away. The same goes with pulling. The problem is when objects are anchored against something. If a player pushes a light object into a wall, the player should start receiving enough force to start pushing them backwards, since the combined mass of the wall and the object are pushing the player back.
Currently, I'm able to do the first part with the following code when a key is pressed:
Note that the force is determined based off the distance from the player to the object and the mass of them.
// dir: push or pull (-1 or 1)
Vector3 directionToPlayer = (dir * (player.transform.position - transform.position)).normalized;
rb.AddRelativeForce(directionToPlayer * f * Time.deltaTime);
player.GetComponent<Rigidbody>().AddRelativeForce(-directionToPlayer * f * Time.deltaTime);
As it is, the code works fine when the objects are just by themselves just by relying on Unity's Physics system. However, it does NOT work when an object is being pushed against a wall, or something really heavy. This is pretty clear as I'm just applying the same force to both the object and the player, and letting Unity decide whether to move the entity based off its rigidbody mass.
My question is, how can I detect if an object is anchored, and if it is combine the mass of the object and the object which it is anchored to, and apply that force to the player? I was thinking how to do this, and I know that I need to figure out the direction of which the force is being applied from, and then determine whether the object that's being pushed or pulled is colliding with anything in that direction, and if so apply a force to the player based off the combined masses. This gets a little tricky however when pushing an object at an angle that's against a wall. For example consider the following scenario:
There is both a horizontal and a vertical component of the force being applied on the cube, and so that should be considered when the cube+wall combined object pushes back on the player. How could this be accomplished or approached? I'm really struggling coming up with how to do this without hard coding direcitons.
Any help is appreciated, and I'll gladly clarify if anything is unclear.
NOTE The system is really based from a book series called Mistborn, but the concept is really close to The Force in Star Wars, and so I'll run with that as more people are familiar with it
This is not a complete solution, but you can use my idea below to acquire the nearby objects and then apply force to your objects and player in accordance with that.
The script should be placed on the object you are pushing or at least use a sphere collider from the object you are pushing.
public List<string> _ValidTargetTags = new List<string> { "Wall" };
public void CheckNearbyArea()
{
//Each of the nearby items will be checked to see if they are a wall or other valid target.
Collider[] ObjectsStruck = ScanForItems(GetComponent<SphereCollider>());
foreach (var o in ObjectsStruck)
{
if (_ValidTargetTags.Contains(o.gameObject.tag))
{
//If wall or other valid target
//Check where wall is placed
//Act according to wall position.
}
}
}
///The method below should find a list of all items inside a spherecollider of the object you are pushing.
Collider[] ScanForItems(SphereCollider sphereCollider)
{
Vector3 center = sphereCollider.transform.position + sphereCollider.center;
float radius = sphereCollider.radius;
Collider[] allOverlappingColliders = Physics.OverlapSphere(center, radius);
return allOverlappingColliders;
}
With this solution you will be able to check the players location relative to any nearby walls. This you can use to calculate what his direction is compared to the wall, relative to the object he is pushing.
I have multiple enemies that move toward the player. I am trying to stop them from merging into each other, i.e maintain some type of minimum distance between each other. What I'm trying is this (from unity3d forums):
enemy1.transform.position = (enemy1.transform.position -
enemy2.transform.position).normalized * distance + enemy2.transform.position;
However, when I have >= 3 enemies they still seem to bunch up even when I apply this to every enemy combination.
I need a better method as this one does not work and does not scale.
What you do around your enemy prefab is place a quad box which in effect is a trigger element, then on you script for the enemy you set that if another enemy (using tag types, I imagine) comes within touching of the quad box then to run appropriate code to stop the enemy getting closer in and to prevent the enemy actually overlapping with this trigger box.
Your code you example in your question looks like it is referencing the enemy units specifically rather than as instance entitites which is very probably a bad way of coding, as you're finding, it's very inflexible dealing with not-specifically-named reference entities.
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
private Transform otherEntity;
public float distance = 50.0f;
private Transform thisEntity;
void OnTriggerEnter(Collider other)
{
otherEntity = other.GetComponent<Transform>();
thisEntity = GetComponent<Transform>();
thisEntity.position = (thisEntity.position - otherEntity.position).normalized * distance + otherEntity.position;
}
}
I have not tested the above code but using the code you reference the values for the transform are loaded from the Game Component for the referenced entities, as this has changed ALOT in Unity since release of version 5.1 and your source for your code was an answer given in 2012!!
thisEntity is the object that the script is attached to, typically one of the enemy. The otherEntity is the object that comes within the quad trigger (please remember the quad needs to be referenced as a trigger element.
The values of the Entity variables need to be set once the trigger is entered, so that it always effects the correct other element.
(I may be totally wrong with my methodology but I hope this helps.)
Update
I've discovered that rigidbody doesn't cast to rigidbody2d. I've tried manually casting, but get errors saying that it can't be done... So my new question is, how can I get joints to work with rigidbody2D?
OP
Learning Unity and am now playing with physics. I've got a small game running and it's all working lovely, but what I'm having issues wrapping my head around is the 2D physics.
I've got various "crates" and each have their own physics values (gravity etc).I've also got a "crate mover" which will (in theory) move crates from one place to another.
However, due to my movers having defined positions they can move to in game space, I'm having terrible trouble getting the crates to "stick" to the movers when they're moved.
So, I did some digging around and found Joints - Specifically FixedJoint - I figured that would solve it, if I attached a joint to the mover and set it's body to the crate? Right? No.
I get this error:
NullReferenceException: Object reference not set to an instance of an object
RobertMover.OnCollisionEnter2D (UnityEngine.Collision2D coll) (at Assets/Scripts/RobertMover.cs:29)
Which relates to the following code:
void OnCollisionEnter2D(Collision2D coll)
{
Debug.Log (coll.gameObject);
FixedJoint j = (FixedJoint)this.gameObject.AddComponent ("FixedJoint");
j.connectedBody = coll.gameObject.rigidbody; // problem line
}
Seeing as I'm still learning Unity, I'm a little unsure as to what is null. My crate has a rigidbody. As does my mover, as I read that joints require them. The object isn't null (checked with the Debug.Log...). The only thing I can think is that the Joint itself is null, which is very odd!
Can anyone explain what I'm doing wrong?
2d physics only works with "2d" classes and methods, you should be using FixedJoint2D or a comparable "2D" joint class if that particular one doesn't exist
I'm working on a Unity game. In it, I want to be able to give different entities different degrees of friction without creating multiple materials in the editor. I'm currently trying to do this by defining a PhysicsMaterial2D as a member variable and instantiating it in the Start method. The material's friction is then applied based on a public member variable. I then set the actor's collider2D's sharedMaterial.
public class ActorUpdateScript : MonoBehaviour {
public float friction;
PhysicsMaterial2D actorMaterial;
void Start () {
actorMaterial = new PhysicsMaterial2D();
actorMaterial.friction = friction;
collider2D.sharedMaterial = actorMaterial;
}
}
I can verify that collider2D.sharedMaterial is indeed receiving the new material, as I can print it's friction and it gives me the expected result. However, no matter what number I give it's friction, it always behaves like the default material. (0.4 friction I believe). The collision boxes he's walking on all have a material with a friction of 1.
What am I doing wrong? Does anyone have any suggestions on how to make unity pay attention to the material I've applied?
Also, before you tell me, I know I can have different materials (high friction, medium friction, low friction, etc) that I apply to different entities. But I'm planning on eventually adding super basic modding support, so the friction for a given entity will be set with a JSON file.
The problem is probably that you have a physics material on both your character and the floor and the combine method is to take the smaller of the two, you will always get the lower value.
To fix this you either remove the physics material from the character, set it high enough it always gets overwritten or change it depending on what you are standing on to alway get the correct behavior.
void Start () {
actorMaterial = new PhysicsMaterial2D();
collider2D.sharedMaterial = actorMaterial;
collider2D.sharedMaterial.friction = friction;
}
Assign new material to collider.sharedMaterial first.
And change material value.
It works for me.