Unity3D checking if a point is inside a game object - android

I am trying to check in Unity if a point(x location of touch,y location of touch) is inside a game object created(Rectangle shaped), if yes, start and spin it around.
I am pretty new to Unity but I tried doing it myself, here is what
Rigidbody rb;
float x, y;
MeshCollider col;
Vector3 v;
bool bo = true;
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody>();
col = rb.GetComponent<MeshCollider>();
}
void Update()
{
if (bo != true)
rb.transform.Rotate(Vector3.back, Time.deltaTime * 200, Space.World);
if (Input.touchCount == 1)
{
x = Input.GetTouch(0).position.x;
y = Input.GetTouch(0).position.y;
Debug.Log(x + "DOTS " + y);
v = new Vector3(x, y, 0);
if (col.bounds.Contains(v))
bo = false;
}
}
My console is not showing anything, also if I type Debug.Log("HELLO"); and I can't pretty much check myself so that is pretty much my code, appreciate any help.

I think you don't get Log due to you are testing on PC, not on mobile device.
In order to check if the touch point is in bounds of gameObject fire a ray from camera:
#if UNITY_EDITOR
if(Input.GetMouseButtonUp(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
#else
if(Input.touches.Length == 1 && Input.touches[0].phase == TouchPhase.Ended)
{
Ray ray = Camera.main.ScreenPointToRay(Input.touches[0].position);
#endif
int layerMask = (1 << YOUR_TARGET_LAYER_ID);
RaycastHit[] hits = Physics.RaycastAll(ray, 100f, layerMask);
foreach(RaycastHit hit in hits)
{
if(hit.collider == col)
{
Debug.Log("Bingo!!");
break;
}
}
}
Note that I used precompiler directives to make possible this code work on mobile device and on PC.
YOUR_TARGET_LAYER_ID is a layer id of the target you want to only be resposive to ray cast. This will ensure that if some other object is covering the target, it will be ignored.

Related

Unity how can i swerve box with use joint?

I want to get an image like in the picture with code. I stacked boxes because i must add joint with code. I want to make the boxes look like this as the character slides left and right smoothly. And how can i smooth swerving control in unity for touch or mouse button?
I tried this codes for movement:
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
firstPos = touch.position;
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.Moved)
Swerving(touch.position);
}
private void Swerving(Vector2 touch)
{
endPos = touch;
float diff = endPos.x - firstPos.x;
transform.Translate(diff * Time.deltaTime * swerveSpeed, 0, 0);
}
But not smooth swerving.
I tried hinge joint for image. I tried random values to motor,spring etc. But it didnt work i have never used joints.
In general when dealing with physics you shouldn't use transform this break collision detection and other physics related things like your joints etc.
Try and rather go through the Rigidbody using e.g. Rigidbody.MovePosition (or accordingly Rigidbody2D.MovePosition if your are in 2D) within FixedUpdate like e.g.
// or Rigidbody2D depending on your needs
[SerializeField] private Rigidbody _rigidbody;
private Vector2 startPos;
private float movement;
private void Awake()
{
if(!_rigidbody) rigidbody = GetComponent<Rigidbody>();
}
// get user input in Update in general
private void Update()
{
if (Input.touchCount > 0)
{
var touch = Input.GetTouch(0);
switch(touch.phase)
{
case TouchPhase.Began:
startPos = touch.position;
movement = 0;
break;
case TouchPhase.Stationary:
case TouchPhase.Moved:
movement = touch.position.x - startPos.x;
break;
default:
movement = 0;
}
}
}
// Apply Physics in FixedUpdate!
private void FixedUpdate()
{
_rigidbody.MovePosition(_rigidbody.position + Vector3.right * movement * Time.deltaTime * swerveSpeed);
}
However, in general the touch is a 2D pixel space position which might be quite different on different devices.
I would rather translate it into a 3D world space position and use something like e.g.
[SerializeField] private Rigidbody _rigidbody;
[SerializeField] private Camera _mainCamera;
private float _offset;
private Plane? _hitPlane;
private Vector3 _targetPosition;
private void Awake()
{
if (!_rigidbody) _rigidbody = GetComponent<Rigidbody>();
if (!_mainCamera) _mainCamera = Camera.main;
}
// get user input in Update in general
private void Update()
{
_targetPosition = _rigidbody.position;
if (Input.touchCount <= 0)
{
return;
}
var touch = Input.GetTouch(0);
switch (touch.phase)
{
case TouchPhase.Began:
{
// Check if you are touching the character
var ray = _mainCamera.ScreenPointToRay(touch.position);
if (Physics.Raycast(ray, out var hit) && hit.rigidbody == _rigidbody)
{
// create a virtual plane parallel to the camera view
// passing the hit point
_hitPlane = new Plane(-ray.direction, hit.point);
// also store the offset from pivot to the hit point
// we only care about the X axis
_offset = (_rigidbody.position - hit.point).x;
}
break;
}
case TouchPhase.Stationary:
case TouchPhase.Moved:
{
if (_hitPlane.HasValue)
{
// now instead keep ray casting against that virtual plane
var ray = _mainCamera.ScreenPointToRay(touch.position);
if (_hitPlane.Value.Raycast(ray, out var distance))
{
var hitPoint = ray.GetPoint(distance);
_targetPosition.x = hitPoint.x + _offset;
}
}
break;
}
default:
_hitPlane = null;
break;
}
}
// Apply Physics in FixedUpdate!
private void FixedUpdate()
{
_rigidbody.MovePosition(_targetPosition);
}
this makes sure your character is definitely placed on the X axis where you are dragging it without any delays but still complying with physics

How can I drag just one object, but not all the objects in Unity? [duplicate]

so as my previous threads show, I am creating a gameObject from sprites images at runtime using this code:
tex = Resources.Load<Texture2D>("pig") as Texture2D;
Sprite sprite = new Sprite();
sprite = Sprite.Create(tex, new Rect(0, 0, 250, 150), new Vector2(0.5f, 0.5f));
GameObject newSprite = new GameObject();
newSprite.AddComponent<Rigidbody2D>();
newSprite.GetComponent<Rigidbody2D>().gravityScale = 0f;
newSprite.AddComponent<ObjectMovement>();
newSprite.AddComponent<SpriteRenderer>();
SR = newSprite.GetComponent<SpriteRenderer>();
SR.sprite = sprite;
As you see I added a script "ObjectMovement", I want to check in this script if someone is dragging this particular gameObject and if so, make it follow the touch position, just to mention - this game is 2D. I never used RaysorRaycast so I am not sure where I gone wrong. Anyway here is my script code:
public SpriteRenderer selection=null;
void Update()
{
if (Input.touchCount >= 1)
{
foreach (Touch touch in Input.touches)
{
Ray ray = Camera.main.ScreenPointToRay(touch.position);
RaycastHit hit;
switch (touch.phase)
{
case TouchPhase.Began:
if (Physics.Raycast(ray, out hit, 100))
selection = hit.transform.gameObject.GetComponent<SpriteRenderer>();
break;
case TouchPhase.Moved:
selection.transform.position = new Vector2(selection.transform.position.x + touch.position.x / 10, selection.transform.position.y + touch.position.y / 10);
break;
case TouchPhase.Ended:
selection = null;
break;
}
}
}
}
So basically - when touching the screen, fire a ray and check which gameObject is in this position, when moving the finger make it follow it. Drag and drop. Thanks.
EDIT: I noticed the script is attached to every gameObject which is not effective, any ideas?
For 2D, you use RaycastHit2D and Physics2D.Raycast instead of RaycastHit and Physics.Raycast. Those are for 3D. Secondly, Make sure to attach a collider to the Sprite. Since this is a 2D game, the collider must have word "2D" in it. For example, Box Colider 2D from the Editor. You can also use Circle Collider 2D.
I noticed the script is attached to every gameObject which is not
effective, any ideas?
Just create an empty GameObject and attach that script to it. That's it.
Here is fixed version of your code:
float tempZAxis;
public SpriteRenderer selection;
void Update()
{
Touch[] touch = Input.touches;
for (int i = 0; i < touch.Length; i++)
{
Vector2 ray = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
RaycastHit2D hit = Physics2D.Raycast(ray, Vector2.zero);
switch (touch[i].phase)
{
case TouchPhase.Began:
if (hit)
{
selection = hit.transform.gameObject.GetComponent<SpriteRenderer>();
if (selection != null)
{
tempZAxis = selection.transform.position.z;
}
}
break;
case TouchPhase.Moved:
Vector3 tempVec = Camera.main.ScreenToWorldPoint(touch[i].position);
tempVec.z = tempZAxis; //Make sure that the z zxis never change
if (selection != null)
{
selection.transform.position = tempVec;
}
break;
case TouchPhase.Ended:
selection = null;
break;
}
}
}
That would only work on mobile but not on the Desktop Build. I suggest you implement IBeginDragHandler, IDragHandler, IEndDragHandler and override the functions that comes with them. Now, it will work with both mobile and desktop platforms.
Note: For the second solution you have to attach the script below to all Sprites you want to drag unlike the first script above.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class Dragger : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
Camera mainCamera;
float zAxis = 0;
Vector3 clickOffset = Vector3.zero;
// Use this for initialization
void Start()
{
//Comment this Section if EventSystem system is already in the Scene
addEventSystem();
mainCamera = Camera.main;
mainCamera.gameObject.AddComponent<Physics2DRaycaster>();
zAxis = transform.position.z;
}
public void OnBeginDrag(PointerEventData eventData)
{
clickOffset = transform.position - mainCamera.ScreenToWorldPoint(new Vector3(eventData.position.x, eventData.position.y, zAxis));
}
public void OnDrag(PointerEventData eventData)
{
//Use Offset To Prevent Sprite from Jumping to where the finger is
Vector3 tempVec = mainCamera.ScreenToWorldPoint(eventData.position) + clickOffset;
tempVec.z = zAxis; //Make sure that the z zxis never change
transform.position = tempVec;
}
public void OnEndDrag(PointerEventData eventData)
{
}
//Add Event Syste to the Camera
void addEventSystem()
{
GameObject eventSystem = new GameObject("EventSystem");
eventSystem.AddComponent<EventSystem>();
eventSystem.AddComponent<StandaloneInputModule>();
}
}

Unity 3d PowerBar

I have been making endless jumping game.
It is lacking powerbar.. I have managed to make one but it does not scale with the screen change.. I tried to use canvas to world screen but bar won't face the direction you click..
So like the longer you hold left mouse click, more power it has and it faces the direction you click.. Atleast it should do that, and i does but only on one screen size.
It looks likes this:
http://prntscr.com/b6z5wn
So this is the code i am currently using..
function Start ()
{
powerFill_startPos = powerFill.transform.localPosition.x;
powerFillAccel = 770 * Time.deltaTime;
}
function Update ()
{
if(Input.GetMouseButton(0) && collision.onPlatform == true && delete.jurinoFlag == true)
{
bar_back.enabled = true;
powerFill_Image.enabled = true;
var moveDirection : Vector3 = gameObject.transform.position - Input.mousePosition;
if (moveDirection != Vector3.zero)
{
var angle : float = Mathf.Atan2(moveDirection.y, moveDirection.x) * Mathf.Rad2Deg;
angle -= 180;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
}
powerFill.transform.localPosition.x += powerFillAccel;
}
else
{
bar_back.enabled = false;
powerFill.transform.localPosition.x = powerFill_startPos;
powerFill_Image.enabled = false;
}
}
I would very much appreciate any help i can get so i can finish the game and publish it :)
Thanks for taking time and replying. Have a nice day!

Unity - Enemy AI; Run away from player (x and y)

I need some help with creating a script for the enemies in my game! I'm making a 2.5D game where you chase campers and try to kill them. I'm mostly done with the game, but I can't get the AI to work! I've looked around for scripts and help for a couple of days now but can't find anything that fits well with the rest of my game... Please help!
For my ground i have a flat surface rotated at 35 on the x-axis, which have worked pretty well for me so far (moving the character around and placing obstacles).
At this point I'm working on this script;
#pragma strict
//Attack button
var attackButton : Joystick;
var anim : Animator;
var delay = 5.0;
//Player can kill
var CanKill = false;
//Score
var scoreValue : int;
var killValue : int;
var playerControl : PlayerControl;
//AI
var speed : int = 2;
var Damp: float = 1.0;
var isRun: boolean = false;
var Target: Transform;
var detectionRange: int = 5;
private var character : CharacterController;
function Start ()
{
anim = GetComponent("Animator");
var playerControlObject : GameObject = GameObject.FindWithTag ("Player");
character = GetComponent(CharacterController);
}
function WaitAndDestroy()
{
yield WaitForSeconds(delay);
Destroy (gameObject);
}
function Update()
{
//Can the player kill?
if (attackButton.tapCount == 1)
CanKill = true;
else CanKill = false;
//AI
var FromPlayer = Vector3(Target.position.x - transform.position.x, 0);
if(FromPlayer.magnitude <= detectionRange){
isRun = true;
}
if(FromPlayer.magnitude >= detectionRange) {
isRun = false;
}
if(isRun) {
RunAway();
anim.SetBool("Walk", true);
}
else anim.SetBool("Walk", false);
}
function OnTriggerEnter (Other : Collider){
if(Other.gameObject.tag == "Player" && CanKill == true) {
playerControl.AddScore (scoreValue);
playerControl.AddKills (killValue);
anim.SetTrigger("Dead");
WaitAndDestroy();
}
}
function RunAway()
{
var moveDirection : Vector3 = transform.position;
character.Move(moveDirection.normalized * speed * Time.deltaTime);
}`
Which kinda works, but for some reason the character stops in the middle of the level and just runs in place... I would also like him to turn and run the other direction if I (the player) catches him and runs in front of him. (If the code is a little messy I apologize, but as I said I'm new to Javascript).
i would done those two changes.
At first:
var FromPlayer = transform.position - Player.transform.position;
cause you want subtract whole vectors not just x coordinates
and second:
function RunAway( FromPlayer :vector3 )
{
character.Move(FromPlayer.normalized * speed * Time.deltaTime);
}
if you have already vector FromPlayer you can directly use it for moving character
i personally never used unity but that is how you would done it anywhere else. It of course assume that positions can be substracted as vectors
You want the campers to run away from the player right? Then you should do
Vector3 moveDirection = transform.position - Player.transform.position
To get the direction they should run in. Then do the line you already have
character.Move(moveDirection.normalized * speed * Time.deltaTime);

How to use the mouse joint in Android?

I want to use the MouseJoint in Java for Android. I am new in box2d and cocos2d. I don't know how to use the mouse joint.
i recomend you to see this tutorial example. Copy from it (sorry i don't like broken links :) ) ...
you drag your body with the help of the MouseJoint, it will collide with the other bodys in the world and apply force to them.
Box2d - Manual - http://www.box2d.org/manual.html#_Toc258082974
8.10 Mouse Joint
The mouse joint is used in the testbed to manipulate bodies with the mouse. It attempts to drive a point on a body towards the current position of the cursor. There is no restriction on rotation.
The mouse joint definition has a target point, maximum force, frequency, and damping ratio. The target point initially coincides with the body’s anchor point. The maximum force is used to prevent violent reactions when multiple dynamic bodies interact. You can make this as large as you like. The frequency and damping ratio are used to create a spring/damper effect similar to the distance joint.
Many users have tried to adapt the mouse joint for game play. Users often want to achieve precise positioning and instantaneous response. The mouse joint doesn’t work very well in that context. You may wish to consider using kinematic bodies instead.
So let's start..
You have to create your PhysicWorld and at least one body in it. ( Checkout the PhysicExample how to.. )
- MouseJoint method
public MouseJoint createMouseJoint(AnimatedSprite box , float x, float y)
{
final Body boxBody =
this.mPhysicsWorld.getPhysicsConnectorManager().findBodyByShape(box);
Vector2 v = boxBody.getWorldPoint(
new Vector2(x/pixelToMeteRatio, y/pixelToMeteRatio)
);
MouseJointDef mjd = new MouseJointDef();
mjd.bodyA = groundBody;
mjd.bodyB = boxBody;
mjd.dampingRatio = 0.2f;
mjd.frequencyHz = 30;
mjd.maxForce = (float) (200.0f * boxBody.getMass());
mjd.collideConnected = true;
mjd.target.set(v);
return (MouseJoint) this.mPhysicsWorld.createJoint(mjd);
}
- Touching Body
we have to override our onAreaTouched method to create an MouseJoint anchor-point on the touch position.
MouseJoint mjActive = null;
private float pixelToMeteRatio = PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT;
#Override
public boolean onAreaTouched(
final TouchEvent pSceneTouchEvent,
final ITouchArea pTouchArea ,
final float pTouchAreaLocalX,
final float pTouchAreaLocalY )
{
if(pSceneTouchEvent.getAction() == MotionEvent.ACTION_DOWN) {
this.runOnUpdateThread(new Runnable() {
#Override
public void run() {
final AnimatedSprite face = (AnimatedSprite)pTouchArea; //The touched body
//If we have a active MouseJoint, we are just moving arround don't create an 2nd one.
if( mjActive == null)
{
Vector2 vector = new Vector2(pTouchAreaLocalX/pixelToMeteRatio,pTouchAreaLocalY/pixelToMeteRatio);
//=====================================
// GROUNDBODY - Used for the MouseJoint
//=====================================
BodyDef groundBodyDef = new BodyDef();
groundBodyDef.position.set(vector);
groundBody = mPhysicsWorld.createBody(groundBodyDef);
//====================================
// CREATE THE MOUSEJOINT
//====================================
mjActive = PhysicsJumpExample.this.createMouseJoint(face, pTouchAreaLocalX, pTouchAreaLocalY);
}
}});
return true;
}
return false;
}
- Moving the body
We are moving our finger over the scene, so we have to move the MouseJoint too.
If we release the finger.. we must destroy the MouseJoint..
#Override
public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
if(this.mPhysicsWorld != null) {
if(pSceneTouchEvent.getAction() == MotionEvent.ACTION_MOVE) {
this.runOnUpdateThread(new Runnable() {
#Override
public void run() {
if( mjActive != null ){ //If the MJ is active move it ..
// =========================================
// MOVE THE MOUSEJOINT WITH THE FINGER..
// =========================================
Vecotr2 vec = new Vector2(pSceneTouchEvent.getX()/pixelToMeteRatio, pSceneTouchEvent.getY()/pixelToMeteRatio);
mjActive.setTarget(vec);
}
}});
return true;
}
//===========================================
// RELEASE THE FINGER FROM THE SCENE..
//===========================================
if( pSceneTouchEvent.getAction() == MotionEvent.ACTION_UP ||
pSceneTouchEvent.getAction() == MotionEvent.ACTION_CANCEL
) {
this.runOnUpdateThread(new Runnable() {
#Override
public void run() {
if( mjActive != null )
{
//======================================
// DESTROY OUR MOUSEJOINT
//======================================
PhysicsJumpExample.this.mPhysicsWorld.destroyJoint(mjActive);
PhysicsJumpExample.this.mPhysicsWorld.destroyBody(groundBody);
mjActive = null;
}
}});
return true;
}
return false;
}
FYI:
To fit your needs, you have to play with this settings ( in the createMouseJoint method )
mjd.dampingRatio = 0.2f;
mjd.frequencyHz = 30;
mjd.maxForce = (float) (200.0f * boxBody.getMass());

Categories

Resources