Search Unity

Increase Size of Plane due to head movemet

Discussion in 'AR/VR (XR) Discussion' started by accom, Apr 12, 2017.

  1. accom

    accom

    Joined:
    Apr 12, 2017
    Posts:
    9
    Hello,

    I am very new to Unity and all the programming area. I have a HTC Vive and want to perform a simple example project.
    There is a plane with a texture in front of me, like a TV screen.
    When I lean my head forward, I wand this plane to increase in size (e.g. triple size).
    Upon leaning my head back into normal position I want the plane to reduce its size to normal.
    Thus using this movement the person can examine the texture on the plane in more detail, when he/she wants.
    How can I make such a program possible?

    Thanks for your help.

    Accom
     
  2. SiliconDroid

    SiliconDroid

    Joined:
    Feb 20, 2017
    Posts:
    302
    Such a scheme would be unsettling in VR; it would break spatial coherence as perceived by the user. The screen is such a large (and contextually important) object in the virtual world that it becomes a worldspace reference; the user would not feel the world was real.

    But if you must try it then the simplest way would be to change the virtual screen scale depending on cameras distance from the screen, put this in the screens update:

    Code (CSharp):
    1.  
    2.         float fDistance = (oCamera.transform.position - this.transform.position).magnitude;
    3.         float fScale = ( 5 - fDistance ) * 2;//TWEAK NUMBERS TO GAIN DESIRED SCALING
    4.         this.transform.localScale = new Vector3(fScale, fScale, fScale);
    5.  
    Note: A better way to achieve your desired effect would be to keep all geometry locked in worldspace and just change what's displayed on the screen by manipulating UV texture etc. But even that is unsettling because of the contextual importance of what is displayed on the screen.

    Probably the best way would be a quantized zoom of just the screens display, like on bladerunner (enhance... enhance...). So have like 5 zoom levels that you snap between depending on head ZPos.

    Also make sure a lot of static geometry is around and behind the screen, to ensure worldspace context is as locked in as possible.
     
    Last edited: Apr 14, 2017
  3. accom

    accom

    Joined:
    Apr 12, 2017
    Posts:
    9
    Hi SiliconDroid,

    Thank you for your help.
    Regarding the break in spatial coherence – I will use the RGB camera attached to the vive to let the user see the surrounding area as an overlay.

    But now to your code: I am sure this is exactly what I need. But unfortunately my programming skills are too poor to apply it directly.
    So I create a new script and paste your code; Do I attach it to the plane? How is the script executed/triggered? Except of manipulating the numbers 2 and 5 that you inserted, do I need to apply/write any other numbers/names to the script?

    Thanks again,
    Accom
     
  4. SiliconDroid

    SiliconDroid

    Joined:
    Feb 20, 2017
    Posts:
    302
    OK, no worries, just name the below script "scale_with_cam_forward" and then drag it onto any object or prefab you wish to scale in your scene with camera push forward.

    I broke out your tweaking variables to the editor:

    "Distance Range" : The push in range you wish to cover with the users head.
    "Maximum Scaling" : As it says, the max scale you wish to ever be applied to object.

    I also added auto calibrate, so if you wish to jump teleport your user somewhere the script will quietly recalibrate behind the scenes and keep working OK.

    I hope you like it and use this as an aid to learn more about coding. With code and time you can do anything you can imagine;).

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    6. //    CLASS:
    7. public class scale_with_cam_forward : MonoBehaviour
    8. {
    9.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    10.     //    EDITOR VARS
    11.     public float DistanceRange = 0.5f;
    12.     public float MaximumScaling = 10.0f;
    13.  
    14.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    15.     //    INTERNAL CONSTANTS
    16.     const float RECALLIBRATE_THRESHOLD = 1.0f;
    17.  
    18.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    19.     //    INTERNAL VARS
    20.     [HideInInspector]
    21.     private float fLastFrameCamDistance = -1000.0f;//FORCE RECALIB ON FIRST FRAME
    22.     private float fInitialCamDistance = 0.0f;
    23.    
    24.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    25.     //    UPDATE
    26.     void Update()
    27.     {
    28.         //  GET CAM
    29.         Camera oCam = Camera.main;
    30.         if (!oCam)
    31.         {
    32.             return;
    33.         }
    34.  
    35.         // GET CAM DISTANCE
    36.         float fCamDistance = (this.transform.position - oCam.transform.position).magnitude;
    37.  
    38.         //  RECALIBRATE INITIAL DISTANCE IF WE SEE A SUDDEN TRANSLATION JUMP OVER ONE FRAME
    39.         if(Mathf.Abs(fCamDistance - fLastFrameCamDistance) > RECALLIBRATE_THRESHOLD)
    40.         {
    41.             fInitialCamDistance = fCamDistance;
    42.         }
    43.         fLastFrameCamDistance = fCamDistance;
    44.  
    45.         //  DERIVE SCALING
    46.         float fCamPushIn = fInitialCamDistance - fCamDistance;
    47.         fCamPushIn = Mathf.Clamp(fCamPushIn, 0, DistanceRange) / DistanceRange;
    48.         float fScale = 1 + (MaximumScaling - 1) * fCamPushIn;
    49.  
    50.         //  APPLY SCALING
    51.         this.transform.localScale = new Vector3(fScale, fScale, fScale);
    52.     }
    53. }
     
    Last edited: Apr 16, 2017
  5. accom

    accom

    Joined:
    Apr 12, 2017
    Posts:
    9
    Hi SiliconDroid,

    thanks incredible. It worked so well. It was really "plug and paly". You are amazing. I started to read the code (as you recommended) so that I can make some changes, but it was not necessary. It is perfect for my little project. All the changes I did to the code made the experience worse. Thanks again.

    There is just one more thing I need to implement. I need to chance a scene by pushing a button.
    Example keystroke "1" load scene "one", keystroke "2" loads scene "two". So I can experiment with different enviroments without leaving Unity.
    Do you have any good ideas?

    Thanks again,
    Accom
     
  6. SiliconDroid

    SiliconDroid

    Joined:
    Feb 20, 2017
    Posts:
    302
    Hi Accom,

    Attach the script below to something that you put in every scene, it could be the main camera if you want, or an empty game object or the floor, anything that you have in each scene.

    NOTE: You must include the scenes you wish to reference in your scene list within unitys build settings panel: https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadScene.html

    Code (CSharp):
    1. using UnityEngine.SceneManagement;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    7. //    CLASS:
    8. public class scene_changer: MonoBehaviour
    9. {
    10.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    11.     //    UPDATE
    12.     void Update()
    13.     {
    14.         if (Input.GetKeyDown(KeyCode.Alpha1))
    15.         {
    16.            SceneManager.LoadScene("SceneName1");
    17.         }
    18.         else if (Input.GetKeyDown(KeyCode.Alpha2))
    19.         {
    20.            SceneManager.LoadScene("SceneName2");
    21.         }
    22.     }
    23. }
     
  7. accom

    accom

    Joined:
    Apr 12, 2017
    Posts:
    9
    Hi SiliconDroid,

    actually, I was inspired by your recommendation to do my own coding and I managed to Change a script that was based on the old "LoadLevel" to the new "Load.Scene" and it worked. But I could not manage to make the script listen to multiple buttons. Now with your help and the "else if" I can do it. I guess I can use "else if" multiple times, so that I can load Scene 1 to 10 by different buttons.

    As a thank for your help I will buy some of your games and tell my friends about them.

    Keep up the way you are (I hope that makes sense in English :) ).

    Accom
     
    SiliconDroid likes this.
  8. SiliconDroid

    SiliconDroid

    Joined:
    Feb 20, 2017
    Posts:
    302
     
  9. SiliconDroid

    SiliconDroid

    Joined:
    Feb 20, 2017
    Posts:
    302
    Excellent,
    yes just keep repeating the else if structure as long as you want.

    Code (CSharp):
    1. if(x == 1)
    2. {
    3.    //DO SOMETHING
    4. }
    5. else if(x == 2)
    6. {
    7.    //DO SOMETHING
    8. }
    9. else if(x == 3)
    10. {
    11.    //DO SOMETHING
    12. }
    13. else if....
    14.  
    Cool beans! And keep coding!;)