I need grip between two objects actually small cube is a player having rigid body and big cube is an object that helps small cube to jump on it and keep jumping on other big cubes to reach to the destination. I need when the player jumps and land on rotating cube so there should friction between them by default the player should rotate with big cube cause its on the big cube.
The expected result was that the small cube having rigid body should also rotate with big cube cause big cube is rotating and is on the big cube:
You can set the small cube gameobject as child of the big cube gameobject. This should to the trick.
----EDIT AFTER COMMENTS
If you need to change the child hiearchy (because the small cube can move away), then you need a script that add and remove the child when required.
=> When player (small cube) is on the big cube you much child player to the big cube.
=> When player (small cube) moves away of the big cube you much de-child player to the big cube.
If you're using rigidbodies you may use OnCollisionEnter and OnCollisionExit.
You may attach this monobehaviour to the big cube.
public class BigCubeScript : MonoBehaviour
{
private void OnCollisionEnter(Collision other)
{
//check if the colliding object is player (here I'm using a tag, but you may check it as you prefer)
if (other.gameObject.tag == "Player")
//change the parent of the player, setting it as this cube
other.transform.SetParent(this.transform);
}
void OnCollisionExit(Collision other)
{
if (other.gameObject.tag == "Player")
//remove the player from the cube
other.transform.SetParent(null);
}
}
You can also apply a force to the rotation of the player until he stays on the cube. In this case it's quite important to balance the rotation force well (you can try it in the editor).
public class BigCubeScript : MonoBehaviour
{
//you may change this to add or remove the force
Vector3 _rotationForce = new Vector3(0, 5, 0);
private void OnCollisionStay(Collision other)
{
var rigidbody = other.gameObject.GetComponent<Rigidbody>();
Quaternion deltaRotation = Quaternion.Euler(_rotationForce * Time.deltaTime);
rigidbody.MoveRotation(rigidbody.rotation * deltaRotation);
}
}
Further info in OnCollisioEnter and OnCollisionExit in this Unity Tutorial
Further info on the Tags in this Unity Tutorial
You could try to constrain position and rotation on Rigidbody of the small cube. After that you could call constrains.none so that you could allow jump again and do that every time the small cube collides with the big one. Hope it helps :)
Related
I have a script that faces my player (cube) to its moving direction. It also has a grappling gun, but when he turns to its moving direction, gun turns too and it can't use grappling gun when i try to grapple and object staying on the opposite site of my player.
This is how i turn my player:
private void Flip()
{
if (isFacingRight && HorizontalInput() < 0f || !isFacingRight && HorizontalInput() > 0f)
{
Vector3 localScale = transform.localScale;
isFacingRight = !isFacingRight;
localScale.x *= -1f;
transform.localScale = localScale;
}
}
If I can fix the localScale of my gun, so that it won't multiplied with -1 when i multiply the whole body.
Any idea? Thanks a lot.
As I understand the question: you want to flip the player but not flip the gun (which is a child of the player).
One way of doing this is to organize the Player object like this:
-Player (prefeb, invisible)
--PlayerGraphicChild (Cube, flip this one only)
--PlayerGunChild (don't flip this one).
Another way is to add a new prefeb called Gun, and set the position of that object to one of the children of Player. Organize the hierarchy like this:
-Player (flip this one)
--PlayerGunDolly (flips with parent)
and create a new prefeb:
-Gun (has a component that sets the transform.position to transform of PlayerGunDolly. Does not flip.)
I have a Gameobject called ball and another called floor. As can be seen in the code, when the ball hits the floor, a printout shall be made.
void OnCollisionEnter2D(Collision2D collision)
{
bg = GameObject.Find(bg_name);
if (collision.gameObject.tag == "floor")
{
//bg.GetComponent<ControlGame>().deleteBall();
//bg.GetComponent<ControlGame>().recreateBall();
print("Ball hit floor");
}
if (collision.gameObject.tag == "rope")
{
bg.GetComponent<ControlGame>().ToggleIsShot(false);
}
}
The problem is that I have moved the floor now, such that the ball and the floor has different depth. Still, the printout is made although the two Gameobjects are not touching. See the screenshots below:
The print is in the lower left corner. Why is that?
According to the comment below, the z-value does not have an effect. But I have also a collision detector for the rope, which is a Bezier-curve with an EdgeCollider2D attached to it. When the rope passes the floor, nothing is triggered in onCollisionEnter2D.
void OnCollisionEnter2D(Collision2D collision)
{
bg = GameObject.Find(bg_name);
if (collision.gameObject.tag == "floor")
{
print("floor collision");
bg.GetComponent<ControlGame>().ShootBall();
}
}
Well, these are Collider2D.
You only changed the Z (depth) position of the floor which basically is completely ignored in a 2D game / by 2D physics.
As you can also see in the GameView for the Physics 2D the objects are still aligned and colliding.
Why isn't it also working for collision between rope and floor?
Please checkout the Collision Action Matrix for which collisions/trigger can be detected.
→ At least one of the objects has to be a Rigidbody2D.
If the rope is e.g. moved by script then it has to be a Kinematic → in this case also the floor would need to be a Rigidbody2D and not Kinematic.
The reason I guess it worked just fine for the ball is because it already is a non-kinematic Rigidbody2D so able to detect collisions with static colliders.
I'm trying to learn Unity by myself. I'm recreating pong in 3d with Unity objects. I started a few minutes ago and every time I throw any input into the pad its y coordinate shifts to 2.6, I have no idea why. Can someone help?
public class PadMovement : MonoBehaviour {
private CharacterController pad;
private Vector3 direction;
private Vector3 movement;
[SerializeField] private float speed = 50.0f;
// Use this for initialization
void Start() {
pad = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update() {
direction = new Vector3(Input.GetAxis("Horizontal"), 0, 0);
movement = direction * speed;
pad.Move(movement * Time.deltaTime);
}
}
SOLVED: there was a capsule collider out of place!
Afternoon, I recently copied your code into a 'Unity3d', ".cs", File and actually I created a cube and placed my game into a 2d mode, After this I named my file "PadMovement", after that I dragged it onto my newly created cube, Once I had done that I tried to click play and noticed that my cube didn't have a "CharacterController", attached to my cube, Once I had done that and clicked play I was eligible to have my "paddle", smoothly move around the screen # 50.0f along the X axis.
Knowingly, My Input came from the "Character Controller", My Speed came from the Serial field you had for speed!
Do you by any chance have a CapsuleCollider Component or some other collider on the same GameObject that you have this PadMovement Component on? That sounds like a height where it might just be trying to pop the object out of ground collision.
It should be harmless if that's all it is. If you really want an object to be at y of 0 you can attach it to a parent object and have that parent stay at 0.
I am have some difficulty with what is probably a very silly thing. I have an enemy gameobject that depending on where it is hit (collision) - either it, or the play dies. I think the simplest way to describe this is by using the classic Super Mario Bros. game as an example.
As you all know, if the player runs into the enemy - the player will lose - UNLESS he jumps on top of the enemy's head, in which case the enemy should die.
My initial idea was to create two colliders on the gameobject:
Blue border represents a BoxCollider2D - that if collided with - will cause player to lose (notice it is slightly lower from the top)
Green border represents a BoxCollider2D on a child gameobject - that if collided with - will cause the gameobject to die.
The following is a simplified version of the code I used:
// Collider #1
public void OnCollisionEnter2D(Collision2D collision)
{
// Trigger 'Game-Over' logic
}
// Collider #2
public void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Player")
{
Destroy(this.gameObject);
}
}
This kind-of works, however momentarily after colliding with Collider #1, Collider #2 is also trigger - and while the enemy is destroyed, the player also loses.
I have been playing with the RigidBody2D values to prevent the player from entering the 2nd collider when hitting the enemy from the top - but apparently with that force / speed, the colliders may be slightly inaccurate (or maybe I'm just doing it wrong?).
I have looked into RayCasts but this seems too complex for something that me appears rather trivial (casting rays on all four sides and four vertices of the player - assuming that the player has a box collider).
What I have resorted to 'for the moment' is a a single collider with a simple piece of code that I am unhappy with, and doesn't always work:
public void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Player")
{
float yVelocity = collision.gameObject.transform.rigidbody2D.velocity.y;
if (yVelocity < 0)
{
Debug.Log("Enemy will lose..." + yVelocity);
Destroy(this.gameObject);
}
else
{
// Trigger 'Game-Over' logic
}
}
}
I'm currently working in 2D mode, but solutions for 3D mode (while maybe more complicated than necessary for my question) will also be considered.
Thanks guys.
as a game developer you always have many ways to solve a problem or make a gameplay.
first of all i have to say you should make a polygon collider 2d fo you objects and chracters. just colliding pictures is not very good as i see you used box cilliders in your game.
a good choice can be that you attach and empty object ot you player and set its position under foots of you player and check of enemy hit that enemy dies else if enemy hit main character object, player dies.
another choice can be when o objects collide check y position of 2 objects. of player was higher he kiils, else enemy kills the player.
if you think more you will find more answers.
you have to examin diffrent ways and find most efficient.
I think it will be easy to disable the other collider when one is triggered. You can easily enable/disable colliders with collider.enabled = true; or collider.enabled = false;
// Collider #1
public void OnCollisionEnter2D(Collision2D collision)
{
// Trigger 'Game-Over' logic
// collider2.enabled = false;
}
// Collider #2
public void OnCollisionEnter2D(Collision2D collision)
{
// collider1.enabled = false;
if (collision.gameObject.tag == "Player")
{
Destroy(this.gameObject);
}
}
This way it will be pretty lightweight and easy to implement.
One way of implementing what you want is to put each collider in its child own game object and use the IsTouching() method.
void OnTriggerEnter2D(Collider2D other){
if(GameObject.Find("Top Trigger").GetComponent<BoxCollider2D>().IsTouching(other)){
Destroy(transform.gameObject)
}
if(GameObject.Find("Bottom Trigger").GetComponent<BoxCollider2D>().IsTouching(other)){
Destroy(other.gameObject)
}
}
I am making my first game in Unity 3D something like tower defense game. I have imported a Fbx model of a tower and attached it to a prefab. Now I want the nozzle of the tower to rotate and follow the enemy as the enemy passes by .
In the fbx model i imported i got I have two poly meshes one for the base of the tower that is fixed, and one for the top of the tower that will rotate. Now I tried to create two different gameObject with these two meshes but if I put them on same point they overlap. So I have to do manual alignment such that the nozzle sit correctly over the base.
I was wondering if there is any other way such that entire towers remain is one gameObject and I can rotate the upper part.
I did manage to solve my problem. Not sure if was the best way , but it works.
To upgrade the towers and transform only the nozzle part I essentially did this.
public class tryFbx : MonoBehaviour {
public GameObject[] ModelPrefab;
GameObject modelInstance;
Renderer rn = new Renderer();
// Attaching the model to prefab at runtime by creating a array of prefabs
public void AttachModelToPrefab(GameObject modelPrefab) {
modelInstance = GameObject.Instantiate(modelPrefab) as GameObject;
modelInstance.transform.position = transform.position;
modelInstance.transform.rotation = transform.rotation;
// Attach the model instance to the prefab shell
modelInstance.transform.parent = gameObject.transform;
}
void Start () {
}
// Update is called once per frame
void Update () {
if (GameManager.upgrade){
AttachModelToPrefab(ModelPrefab[GameManager.towerUpgradeLevel]);
foreach ( Renderer r in modelInstance.GetComponentsInChildren<Renderer>()){
// "polySurface98" is the name of the mesh I want to rotate. The tower and its upgrade have the same name.
if (r.name == "polySurface98")
rn = r;
}
// apply any transformation to the partial fbx
rn.transform.Translate(1,1,1);
}
}
}
You can create a hierarchy of GameObjects; you'll have one parent GameObject representing the tower and 2 children, being that you rotate one of them. Note that the coordinates of the children will be in relation to the parent's, so any "messy" manual calibration you make on the children will be contained.
Or, more complicated, you can create only one mesh that has an animation and apply it to one GameObject.