Using ARCore on Unity, I'm trying to place one gameObject between two gameObjects. Unfortunately it doesn't display, it seems it is a problem with Anchor.
*Using Vuforia, i didn't had problem to position game objects.
What i try to achieve is:
Place two objects (A and B) on the ground when i touch the surface. It Works
Place a gameObject (C) between the two objects (A and B).Not displaying
// Place target objects A and B on surface touch
GameObject prefab;
GameObject prefab2;
prefab = AndyPointPrefab;
prefab2 = AndyPlanePrefab;
hitpoint= hitpoint + 1;
// Place object A
if (hitpoint==1){
target1 = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
target1.transform.Rotate(0, k_ModelRotation, 0, Space.Self);
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
target1.transform.parent = anchor.transform;
mIsFirsttargetVisible=true;
}
else if (hitpoint==2){ // Place object B
target2 = Instantiate(prefab2, hit.Pose.position, hit.Pose.rotation);
target2.transform.Rotate(0, k_ModelRotation, 0, Space.Self);
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
target2.transform.parent = anchor.transform;
mIsSecondTargetVisible=true;
hitpoint=-1;
}
//Update function : todisplay point C in-between.
Update() {
// Place object C
if(mIsFirsttargetVisible && mIsSecondTargetVisible){
GameObject objectMiddle = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Vector3 middlePosition = (target1.transform.position+target2.transform.position)/2;
objectMiddle.transform.position = middlePosition;
objectMiddle.transform.localScale = new Vector3(200.0f, 10.0f, 200.0f);
}
}
EDIT
I successfully arrived to place the gameobject in between.
i added this last line in my code: target1.transform.parent = objectMiddle.transform;
if(mIsFirsttargetVisible && mIsSecondTargetVisible){
GameObject objectMiddle = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Vector3 middlePosition = (target1.transform.position+target2.transform.position)/2;
objectMiddle.transform.position = middlePosition;
objectMiddle.transform.localScale = new Vector3(200.0f, 10.0f, 200.0f);
target1.transform.parent = objectMiddle.transform;
}
Related
I've searched around and can't seem to find a write up on the calculations I might need for placing an object onto another one without them placing halfway inside of eachother.
private void MovePlaceableObject()
{
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
Debug.DrawRay(ray.origin, ray.direction * 20f);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, 15f))
{
Vector3 newPosition = hit.point;
currentPlaceableObject.transform.position = newPosition; //move object to where we have the mouse
currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal); //rotation equal to the current rotation of our hitinfo, then up
}
}
private void HandeNewObjectHotkey()
{
if (Input.GetKeyDown(newObjectHotkey))
{
if(currentPlaceableObject == null)
{
currentPlaceableObject = Instantiate(placeableObjectPrefab);
//currentPlaceableObject.GetComponent<BoxCollider>().enabled = false;
}
else
{
Destroy(currentPlaceableObject); //pressing the button again will destroy current object
}
}
}
I've tried storing the object I'm looking at's size to floats for x,y,z and a vector3 for it's position, and tried fiddling around with adding those to the newPosition with the hit.point to no avail.
I've wracked my brains for about a day now, i'm terrible at math, however I know that you must need to get the current object your looking ats position or size, then factor that into your placement right?
Get the size of the object that you are looking at by accessing its collider component. You can use the bounds property of the collider to get its size.
Bounds objectBounds = hit.collider.bounds;
Calculate the center point of the object by adding half of its size to its position.
Vector3 objectCenter = hit.collider.transform.position + objectBounds.extents;
Calculate the position of the new object by adding the size of the new object to the center point of the object that you are looking at. This will place the new object on top of the other object.
Bounds newObjectBounds = currentPlaceableObject.GetComponent<Collider>().bounds;
Vector3 newObjectPosition = objectCenter + new Vector3(0, newObjectBounds.extents.y, 0);
Set the position of the new object to the calculated position.
currentPlaceableObject.transform.position = newObjectPosition;
You can also set the rotation of the new object to match the normal of the surface that it is being placed on, as you are already doing in your code.
currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
The code I am using currently makes the enemy notice me at a distance then follow me if I get closer. The issue I am having is with how they move. I am building a Minecraft style game but I cant get the enemies to stay on the ground and jump up each block like I have too with the fps controller. They just seem to float the shortest distance possible towards me.
Code:
var target : Transform; //the enemy's target
var moveSpeed = 3; //move speed
var rotationSpeed = 3; //speed of turning
var range : float=10f;
var range2 : float=10f;
var stop : float=0;
var myTransform : Transform; //current transform data of this enemy
function Awake()
{
myTransform = transform; //cache transform data for easy access/preformance
}
function Start()
{
target = GameObject.FindWithTag("1Player").transform; //target the player
}
function Update () {
//rotate to look at the player
var distance = Vector3.Distance(myTransform.position, target.position);
if (distance<=range2 && distance>=range){
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
}
else if(distance<=range && distance>stop){
//move towards the player
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
else if (distance<=stop) {
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
}
}
Okay now here is what you are missing:
1.Lock the rotation on x and z axis to zero
myTransform.eulerAngles = new Vector3(0f, myTransform.eulerAngles.y, 0);
Just add this line at the end.
2.Make a short distance raycast in front of the AI and if it detects some obstacle, stop the current movement and move by y axis, if there is no obstacle move like you wrote in your script.
As for the raycasting goes, there is no need for me to write it here, you can find more info about it in Unity3D documentation here:
http://docs.unity3d.com/ScriptReference/Physics.Raycast.html and this tutorial is good for staters: https://unity3d.com/learn/tutorials/modules/beginner/physics/raycasting
I am trying to make a Scrabble word game using a fixed camera, but I have a simple issue.
I add some boxes as game objects and the number of these boxes is the length of the word so if the word is "Fish" we will add 4 boxes dynamically. I did that successfully, but I can't center those boxes in the screen. I tried to add those game objects as children under another game object, then center the parent, but with no effect.
This is my code:
void Start () {
for (int i=0; i<word.Length; i++) {
GameObject LetterSpaceObj = Instantiate(Resources.Load ("LetterSpace", typeof(GameObject))) as GameObject;
LetterSpaceObj.transform.parent = gameObject.transform;
LetterSpaceObj.transform.localPosition = new Vector2(i*1.5f,0.0f);
LetterSpaceObj.name = "LetterSpace-"+count.ToString();
count++;
}
gameObject.transform.position = new Vector2 (0.0f, 0.0f);
}
This image shows you the idea:
I believe your code is working, but the problem is that your first letter is located at your parent object, and then every letter from then on is added to the right. That means that when you center the parent object what you are doing is putting the first letter in the center of the screen.
If you run the game and use the scene view to look at where the parent object is this can confirm this. What you can do instead is that rather than placing the parent at the center of the screen, offset it by an amount equal to the length of the word.
gameObject.transform.position = new Vector2 (-(word.Length / 2.0f) * 1.5f, 0.0f);
You might also want to consider changing some of those constants, such as the 1.5f into variables with names like LetterSize or basing it off the actual prefab so that way any future changes will work automatically.
This is the last solution after some edits to fix this issue.
GameObject LetterSpaceObjRow;
int count = 1;
string word = "Father";
float ObjectXPos;
float LocalScaleX;
void Start () {
for (int i=0; i<word.Length; i++) {
GameObject LetterSpaceObj = Instantiate(Resources.Load ("LetterSpace", typeof(GameObject))) as GameObject;
LocalScaleX = LetterSpaceObj.transform.localScale.x;
ObjectXPos = i*(LocalScaleX+(LocalScaleX/2));
LetterSpaceObj.transform.parent = gameObject.transform;
LetterSpaceObj.transform.localPosition = new Vector2(ObjectXPos,0.0f);
LetterSpaceObj.name = "LetterSpace-"+count.ToString();
count++;
}
gameObject.transform.position = new Vector2 (-(ObjectXPos/2.0f) , 0.0f);
}
I understand that I can use leapmotion in game with Unity3D.
What I can't see any information on, is if I can use it to actual interact with assets, models etc as I build the game. For example revolving a game object around the x axis or zooming in or out of the view.
Is this possible?
Yes, it is possible, but requires some scripts that nobody has written yet (ASFAIK). Here is a VERY rough example that I worked up today since I've been curious about this question, too.
All it does is move, scale, and rotate a selected game object -- it doesn't try to do this in a good way -- it is a proof of concept only. To make it work you would have to do a sensible conversion of Leap coordinates and rotations to Unity values. To try it, put this script in a folder called "Editor", select a game object in the scene view and hold a key down while moving your hand above your Leap. As I said, none of these movements really work to edit an object, but you can see that it is possible with some sensible logic.
#CustomEditor (Transform)
class RotationHandleJS extends Editor {
var controller = new Leap.Controller();
var position;
var localScale;
var localRotation;
var active = false;
function OnSceneGUI () {
e = Event.current;
switch (e.type) {
case EventType.KeyDown:
position = target.transform.position;
localScale = target.transform.localScale;
localRotation = target.transform.localRotation;
active = true;
Debug.Log("editing");
break;
case EventType.KeyUp:
active = false;
target.transform.position = position;
target.transform.localScale = localScale;
EditorUtility.SetDirty (target);
break;
}
if(active){
frame = controller.Frame();
ten = controller.Frame(10);
scale = frame.ScaleFactor(ten);
translate = frame.Translation(ten);
target.transform.localScale = localScale + new Vector3(scale, scale, scale);
target.transform.position = position + new Vector3(translate.x, translate.y, translate.z);
leapRot = frame.RotationMatrix(ten);
quats = convertRotation(leapRot);
target.transform.localRotation = quats;
}
}
var LEAP_UP = new Leap.Vector(0, 1, 0);
var LEAP_FORWARD = new Leap.Vector(0, 0, -1);
var LEAP_ORIGIN = new Leap.Vector(0, 0, 0);
function convertRotation(matrix:Leap.Matrix) {
var up = matrix.TransformDirection(LEAP_UP);
var forward = matrix.TransformDirection(LEAP_FORWARD);
return Quaternion.LookRotation(new Vector3(forward.x, forward.y,forward.z), new Vector3(up.x, up.y, up.z));
}
}
At the moment I have a script which when you hit a cube, it follows the player...but when you stand still it overlaps you. What I want is to be able to set the position of the cube to five steps behind the player at all times...how would i do this?
GameObject.Find("Cube2").transform.position = Vector3(0.5, 0.5, 0.5);
That is what I have tried so far, but that just makes the cube disappear?
the script in its entirety:
static var target : Transform; //the enemy's target
var moveSpeed = 3; //move speed
var rotationSpeed = 3; //speed of turning
var Player = GameObject.Find("Player").transform.position;
var Cube2 = GameObject.Find("Cube2").transform.position;
var myTransform : Transform; //current transform data of this enemy
function Awake()
{
//myTransform = transform; //cache transform data for easy access/preformance
}
function Start()
{
//target = GameObject.FindWithTag("Player1").transform; //target the player
}
//var distance = Vector3.Distance(Player.transform.position, Cube2.transform.position);
//Debug.Log(distance);
function Update () {
Debug.Log(Player);
//var distance = Vector3.Distance(Player.transform.position, Cube2.transform.position);
//var distance = Vector3.Distance(player_distance, cube_distance);
// if (distance > 5)
// {
if (target == GameObject.FindWithTag("Player").transform)
{
//rotate to look at the player
GameObject.Find("Cube2").transform.position = Vector3(0.5, 0.5, 0.5);
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
//move towards the player
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
//}
}
Like I said, I don't know unity really (had a 5 minute play with it)
In honesty it looks like you've pretty much got it - not sure why you can't get it working:
This is what should work: (assuming the quarternion calls are correct) - this is using latest Unity reference from the site so it might be diff to what works for you (what version of Unity you on?)
// Params
var moveSpeed = 3; // Move speed
var rotationSpeed = 3; // Speed of turning
// Find game objects
var Player = GameObject.Find("Player");
var Cube2 = GameObject.Find("Cube2");
function Update ()
{
// Vector from cube pos to player pos (vector math: target - position = vector to target from pos)
var dir = Player.transform.position - Cube2.transform.position;
// If the distance is over 5 units
if(dir.magnitude > 5.0f)
{
// Rotate towards player
Cube2.transform.rotation = Quaternion.Slerp(Cube2.transform.rotation, Quaternion.LookRotation(dir), rotationSpeed * Time.deltaTime);
// Move forward at specified speed
Cube2.transform.position += Cube2.transform.forward * moveSpeed * Time.deltaTime;
}
}
That should do it - if not let me know what happens (or if you get compilation errors) - like I said I don't really know Unity but I've had a look and I'm familiar with 3D/game programming