Unity AR Rotate Scene to match reference point - unity3d

How to Match a reference point in 2 different AR scenes by position and rotation?
Here are some details about my project:
I have 2 scenes: "new scan" and "load scan". In the "new scan" scene I instantiate a 3d cube and make all the other points relative to it. This is my reference point. Then I instantiate some more points and finally save all the data to the device (my phone).
Next, in "load scan" I load the scene again and instantiate the cube in the exact same world position. For now, I managed to set the right position for each point but the axis is rotated because I start the scene from a different real-world location and different phone rotation.
Based on the cubes which are instantiated in the same place, I need to match the rotation and the position of the scene so the points will appear in the same relative position as the first cube.
Note: one can assume that the cube will instantiate with the user standing in the same direction as the desired position. But Do NOT assume that the user starts the "load scan" scene in the same direction as the "new scan" scene (which effect the whole scene rotation).
Here is a visualization of the problem:
Image of New Scan:
Image of Load Scan:
Thanks

If you want to make sure that the cube will appear in the same position/rotation in every AR session you have several options:
Use an Image marker
Use ARWorldMap (iOS exclusive)
Use a Cloud Tracking solution (google cloud anchors / Azure spatial anchors)
Of course you can also try to make the user place the cube correctly themselves, or redesign your app to work without these restrictions.

So I've found a solution but this is not the ultimate solution:
First, make a class with public static parameter so we can pass it through other scripts and scenes. Something like that:
public static class SceneStage
{
public static int ResetScene = 0;
}
Now, every time the camera turns on, check the SceneStage.ResetScene state. If value == 0 don't do anything, otherwise ask the user to stand facing the desire direction and then press a button, which call the function ResetScene:
private void ResetScene(int _scene)
{
var xrManagerSettings = UnityEngine.XR.Management.XRGeneralSettings.Instance.Manager;
xrManagerSettings.DeinitializeLoader();
SceneManager.LoadScene(_scene); // reload current scene
xrManagerSettings.InitializeLoaderSync();
}
Here I send the scene build index to the function with:
ResetScene(SceneManager.GetActiveScene().buildIndex);
So basically, the flow is like that: for the first time we open the scene (when SceneStage.ResetScene = 1) -> change the value to 0, and reset the scene. The second time don't do anything, but when we leave the scene set the value back to 1 so the next scene will reset too (because the ARPose driver still tracking the environment).

Related

Unity Arfoundation placed object is not static

Added FeatheredPlanes scene from samples to my project.
The problem is: when the content
https://gyazo.com/685b86f10b01e734dac14d57ee7a022e
is per-defined (set the cube or any object before building) - everything works fine.
When the object is set dynamically, my object is loading from the server and then is setting to the "content", then after placing it to the virtual plane - it starts to move if i move my camera.
The problem was model's pivot point.
It was at the center of the model, and all i had to do, is to offset the model, so the bottom part of the model is leveled with the floor.

Can I place an object in air - 360 angle (random position) without click instead of find plane in unity Vuforia mid air

I'm trying to show my 3D object in mid air. Currently my object shows on click event, but I don't want click event. I just want the object shown in a random position in midair.
if I break your question into two, then,
Vuforia uses "Anchor input Listener Behavior" to receive the input for the mid-air anchor. I am not sure it will work without a click event.
you have to click to lock the mid-air target, you can gamify it by showing a pop up "click to start".
However, there is always a way out. If you go through PlaneManager.cs class then you fill find a method "PlaceObjectInMidAir", you can carefully build logic and call the following lines in Update method but for one time.
if (TrackingStatusIsTrackedAndNormal)
{
this.contentPositioningBehaviour.AnchorStage = this.midAirAnchor;
this.contentPositioningBehaviour.PositionContentAtMidAirAnchor(midAirTransform);
UtilityHelper.EnableRendererColliderCanvas(this.midAirAugmentation, true);
this.midAirAugmentation.transform.localPosition = Vector3.zero;
UtilityHelper.RotateTowardCamera(this.midAirAugmentation);
}
To spawn the gameobjects randomly in 360 degree, you can use instantiate method in random position with "Random.insideUnitSphere" [see the link]
https://docs.unity3d.com/ScriptReference/Random-insideUnitSphere.html
then make that object child of mid-air Achor "Anchor_MidAir".
Hope my answer would give you a start push.
Good luck!
currently my object show on click event i don't wont click event just object show on random position of midair
If I understand that correctly, your object is shown when the mouse is clicked, and instead of this you want to show it in a random position. Here's what you should do:
Don't listen to that click event. If you don't want something to happen on click, just don't write any code that does that!
To teleport an object to a random position, decide what the minimum and maximum values for your object's position are, and do the following:
yourGameObject.transform.position = new Vector3(
Random.Range(minX, maxX),
Random.Range(minY, maxY),
Random.Range(minZ, maxZ));

Unity3d - Need to hide a group of objects in the area

I've already tried depthmask shaders and examined some other ideas, but it seems like it doesn't suit me at all.
I'm making an AR game and I have a scene with a house and trees. All these objects are animated and do something like falling from the sky, but not all at once, but in sequence. For example, the house first, then trees, then fence etc.
(Plz, look at my picture for details) http://f2.s.qip.ru/bVqSAgcy.png
If user moves camera too far, he will see all these objects stucking in the air and waiting for their order to start falling, and it is not good. I want to hide this area from all sides (because in AR camera can move around freely) and make all parts visible only when each will start moving (falling down).
(One more screen) http://f3.s.qip.ru/bVqSAgcz.png
I thought about animation events, but there are too many objects (bricks, for example) and I can't handle all of them manually.
I look forward to your great advice ;)
P.S. Sorry for my bad english.
You can disable their(the objects that are gonna fall) mesh renderers and re active them when they are ready to fall.
See here for more details about mesh renderer.
Deactivate your Object. You might use the camera viewport coordinates to get a y position outside the viewport. They start on the bottom left of the screen (0,0) and go to the top right of the screen (1,1). Convert them to worldspace coordinates. Camera.ViewportToWorldPoint
Vector3 outsideCamera = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 1.2f, 10.0f));
Now you can use the intended x and z positions of your object. Activate it when you want to drop it.
myObject.transform.position = new Vector3(myObject.transform.position.x, outsideCamera.y, myObject.transform.position.z);
Another thing you could additionally do is scaling the object from very small to its intended size when it is falling. This would prevent the object being visible before falling when the users point the camera upwards.
1- Maybe you can use the Camera far clipping plane property.
Or you can even use 2 Cameras if you need to display let's say the landscape on one (which will not render the house + trees + ...) with a "big" far clipping plane and use a second one with Depth only clear flags rendering only the items (this one can have a smaller far clipping plane from what I understand).
2- Other suggestion I'd give you is adding the scale to your animation:
set the scale to 0 on the beginning of animation
wait for the item to be needed to fall down
set the scale to 1 (with a transition if needed)
make the item fall down
EDIT: the workaround you found is quite just fine too! But tracking only world position should be enough I think (saving a tiny amount of memory).
Hope this helps,
Finally, the solution I chose. I've added this script to each object in composition. It stores object's position (in my case both world and local) at Start() and listening if it changes in Update(). So, if true, stop monitoring and set MeshRenderer in on state.
[RequireComponent(typeof(MeshRenderer))]
public class RenderScript : MonoBehaviour
{
private MeshRenderer mr;
private bool monitoring = true;
private Vector3 posLocal;
private Vector3 posWorld;
// Use this for initialization
void Start()
{
mr = GetComponent<MeshRenderer>();
mr.enabled = false;
posLocal = transform.localPosition;
posWorld = transform.position;
}
// Update is called once per frame
void Update()
{
if (monitoring)
{
if (transform.localPosition != posLocal || transform.position != posWorld)
{
monitoring = false;
mr.enabled = true;
}
}
}
}
Even my funny cheap сhinese smartphone is alive after this, so, I guess, it's OK.

SetScale unintentionally affecting SKSpriteNode position

I'm making my first shooter game using Swift and SpriteKit and I've recently been running into problems with setScale(). I have a Laser class whose instances are added as children to a Ship class. I now realize that any down scaling of the parent node will scale its child as well. In my update method in GameScene I check the position of each child named 'Laser' to determine if it should be removed from its parent when offscreen. I recently updated some of my sprites- including their relative sizes, and I noticed that the position of each laser is way off, as they are removed far before they reach the end of the screen and upon debugging their x positions are in fact far larger than where they are displayed onscreen. I also noticed that the starting x of each Laser instance is relative to its original position within the Ship instance. So the ship may be halfway across the screen but the laser x position still starts at 0 and if the ship is able to pass the laser, the laser's position becomes negative--is there a way to grab its position on the screen rather than relative to its start within its parent?
This is the code I'm doing the check with:
self.aShip.gun.enumerateChildNodesWithName("laser",
usingBlock: { node, _ in
if let aLaser = node as? Laser { i
if(aLaser.position.x > self.size.width){
aLaser.removeFromParent()
}
}
}
)
It seems like scaling has a ton more baggage than I would normally assume, so any insight into this problem or how to manage the relation between code and sprites would be awesome!!
EDIT:
I found that adding let positionInScene = self.convertPoint(aLaser.position, fromNode: self.aShip.gun) under if let aLaser = node as? Laser {and consequently using positionInScene rather than the aLaser position works.. however, I still don't fully understand the scaling effect going on with aLaser and it's position and don't know if its efficient to have to convert positions like this at the rate of update (60 times a second).

Q: How do I move objects down the y axis as my player moves up?

Creating a game like Doodle Jump where my player is constantly being moved up by bouncing off of obstacles. Ive tried every trick in the book but nothing seems to be working/doing exactly what I want. Can anyone give me some tips?
iOS 9 introduced the Camera Node. Use SKCameraNode, which is a subclass of SKNode, and can be translated and rotated in same way.
So, instead of moving all of your background elements in the opposite direction of your hero/player, you can simply attach your scene's camera node to your hero/player and the rest is taken care of.
PS. You can also do cool stuff like scaling the camera size.
EDIT.
Happy to include an example.
First, make a camera constant in your scene.
import SpriteKit
class myFirstScene: SKScene {
let myCamera: SKCameraNode = SKCameraNode()
...
}
Then in your didMoveToView() function, assign the scene's built-in camera variable to the camera constant we made earlier.
override func didMoveToView( view: SKView ) {
camera = myCamera
...
}
Now, there are a few different ways to "attach" your camera to your hero/player. The first is to attach your camera node to your hero.
hero.addChild( myCamera )
I don't even know if it works that easily because my game uses something different, a simpler version is below.
update(){
camera!.zRotation = hero.zRotation
camera!.position = hero.position
}