留档Unity代码记录

Unity和VR开发的初级代码记录
注:unity版本号5.4.4,steamvr 版本号1.2.1,VRTK版本号3.1.0。
由于unity版本变更会带来无数错误和代码不能用,以下代码仅用于本版本环境。


目录


VRTK按键事件用法

VRTK_SDK_Bridge.IsTriggerPressedOnIndex(controllerIndex)

VRTK控制器调用方式

 public struct ControllerInteractionEventArgs
    {
        public uint controllerIndex;
        public float buttonPressure;  //按键按下幅度——压力
        public Vector2 touchpadAxis;//触摸的位置坐标x,y -1.0 到 1.0
        public float touchpadAngle;//触摸板上的顺时针方向 0-360
    }


用法:(参考委托调用)

    void DebugLogger(uint index, string button, string action, ControllerInteractionEventArgs e)
    {
        Debug.Log("Controller on index '" + index + "' " + button + " has been " + action 
                + " with a pressure of " + e.buttonPressure + " / trackpad axis at: " + e.touchpadAxis + " (" + e.touchpadAngle + " degrees)");
    }

    void DoTriggerPressed(object sender, ControllerInteractionEventArgs e)
    {
        DebugLogger(e.controllerIndex, "TRIGGER", "pressed down", e);
    }

VRTK示例用法221版本

007 地形调整传送
cameraRig上脚本VRTKHEIGHT ADJUST TELEPORT。可以勾游戏区域下落(Play space Falling),可选无法传送区域(ignore target tag),可用重力gravity(超过几米自由落体)。


009 贝塞尔曲线传送
手柄脚本,绑上以后按圆盘出现曲线,位置传送。


010 地形传送
bezier pointer脚本上可以选射线造型custom pointer tracer.可选落地目标造型custom pointer cursor。
              可选长度Pointer Length和密度Pointer Density.线曲率BeamCurveOffset

011 头盔碰撞消隐
在Camera(eye)上加脚本VRTK_HeadsetCollisionFade,碰撞变黑,可改颜色。
可用忽略某tag或者仅对某tag起效参数。


012 带区域碰撞的曲线传送
cameraRig上脚本VRTK_HEIGHT ADJUST TELEPORT
Controller上脚本bezier和controller events
和009一样,只是勾上bezier中的Show Play Area Cursor和Handle Play Area Cursor Collision显示和提起整个游戏区域移动


018 空间fps(测试用)
加入prefab名FramesPerSecondCanvas。添加Camera(eye),距离0.5-0.8.
子物体rect 
transform调整y值让数字去视野上下方

023 抓取为控制器的子物体(射箭)
弓体:VRTK_Interactable object
(可交互物体)开启抓取,反选HOLD button掉落
bow aim瞄准目标
bow animation动画
把手部分bow handle传入连接点和弓体

箭体:可抓取目标;arrow notch
子物体箭:arrow箭体特性
箭箱:arrow spawner生成箭体
靶子:breakable_cube可击毁目标



025 控制器概览
sliders:滑动块
slidergroup/slider为滑动块核心
配备脚本为VRTK_Slider;ControlReactor(控制反应)
Knob:旋钮
配备脚本为VRTK_Knob;ControlReactor(控制反应)


028 屋内物体
可以开关的盒子,拉门,抽屉,可抓取物品,可开关火机,可随动气球。

029 提示条(2个Prefabs,做子物体)
ControllerTooltips手柄功能提示
ObjectTooltip物品提示
027 小地图跳转(有用!)桌面上的小地图,指哪跳哪,同时带着地图桌。
把桌子作为camerarig的子物体。地图点增加脚本ModelVillage_teleport Location,附上Destination的transform


030 圆形空间菜单
可以放在手柄或物体上,脚本RadialMenu相同,另一个控制脚本不同。更换按钮在buttons/element/button icon


031 凝视传送
camera(eye)上加入VRTK_BezierPointer,按键后传送。

032 自定义控制器模型
控制器默认手型,握住光剑按扳机可以出剑,握住手枪按键发射。修改脚本LightSaber和Gun。



035 控制器高光提示
控制器按键时高亮键位并且加提示条。
碰到物体时,左边为外边描线,右控制器为整体高亮。
Outline Object Copy Highlighter可用在控制器或者物体上(见005)
VRTK_ControllerAppearance_Example用在控制器高亮上。

036 自定功能指示器
左手为直线带末端模型,可以指示圆球转动
右手为曲线模型跳跃。

037 爬楼掉落示例
(爬云梯,爬高楼)
cameraRig加脚本VRTK_PlayerClimb和VRTK_HeightAdjustTeleport
InteraObj脚本中GrabAttachMechanic为Climbable

038 猛冲移动
移动中有快速运动感
cameraRig加脚本DashTeleport

039
自适应质量渲染

VRTK示例用法310版本

034_Controls_InteractingWithUnityUI
与UI互动基本功能:右手按住圆盘出现直线,选定按钮或键盘后按扳机键确认。
左手按住圆盘后出现头显指针,按左手扳机键确认。
左手挂接VRTK_controller Events
右手挂接VRTK_controller Events,VRTK_controller Actions,VRTK_Interact Touch,VRTK_UI Pointer,VRTK_controller UI Pointer Events_listerner,VRTK_Pointer,VRTK_StraightPoint Renderer
headset挂接VRTK_UI Pointer,VRTK_Pointer,VRTK_StraightPoint Renderer,VRTK_Transform Follow
(Pointer用来传送,用来挂接Renderer。UI Pointer用来交互)

默认画布上挂载VRTK_UI Canvas之后,可以被UIpointer选中,普通画布不会有反应。
例子中的UI_Interactions脚本为实例脚本,如在按钮点击事件中选中触发哪个方法,实际会有反应。
Toggle(bool state)为对勾选择开关
Dropdown为下拉菜单


脚本间调用函数或参数

找到GameObject,直接
GameObject.Find("Switch").GetComponent<SwitchGameObject>().Switch=true; //参数赋值
GameObject.Find("Switch").SendMessage("SwitchON");  //可以调public和private
GameObject.Find("Switch").GetComponent<SwitchGameObject>().SwitchON(); //只能调public


void OnMouseOver(){  
        GameObject.Find ("Spotlight").GetComponent<LookAtCube> ().target = newTarget;  
        //直接使用GetComponent<LookAtCube>()s是无法访问到target变量的,会返回null,  
        //原因在于LookAtCube不是附在Cube上的Component,而是附在Spotlight上的,  
        //GetComponent只能获得当前Object上的Component。  
        GetComponent<Renderer>().material.color = new Color(1f,0f,0.5f);

粒子碰撞

粒子碰撞条件
collision选择world 3D
勾选send collision message。

委托调用

delegate委托用法

using UnityEngine;
using System.Collections;

public class delegateTest : MonoBehaviour {
    delegate void PrintSomething();//定义委托,注意返回类型和参数
    PrintSomething m_print;//定义委托变量(委托是一个数据类型)
    void Start() {
        m_print = GUI1;//使委托变量指向一个方法,亦可以使用+=运算符使委托变量指向多个方向,执行m_print();时就会执行附加在其上的所有方法。
    }
    //要执行的委托方法
    void GUI1() {
        Debug.Log("GUI01");
        GUI.Label(new Rect(100,100,100,100),"GUI1");
    }

    void GUI2()
    {
        Debug.Log("GUI02");
        GUI.Label(new Rect(100, 100, 100, 100), "GUI2");
    }

    void OnGUI() {
        if (GUI.Button(new Rect(0, 0, 100, 100), "GUI1")) {
            m_print = GUI1;//改变委托变量指向的方法
        }
        if (GUI.Button(new Rect(100, 0, 100, 100), "GUI2"))
        {
            m_print = GUI2;
        }
        m_print();//执行委托变量指向的方法
    }
}

移动

前向移动
this.transform.Translate(Vector3.forward*Time.deltaTime*speed);

示例一个frefab,刚体化并施加力
GameObject ball =GameObject.Instantiate(ballprefab);
ball.name = "Ball " + nextBallNumber;
ball.transform.position = this.transform.position;
ball.transform.localScale = new Vector3 (0.2f, 0.24f, 0.2f);
ball.AddComponent<Rigidbody> ();
ball.GetComponent<Rigidbody>().mass=0.01f ;
ball.GetComponent<Rigidbody>().useGravity=false ;
ball.GetComponent<Rigidbody>().AddForce(new Vector3(0,50,0),ForceMode.Acceleration);

转盘实现

主轴rigidbody,为Kinematic
轮盘为rigidbody,Hinge Joint连轴,方向沿轴。VRTK InteraOb为可抓起,精确抓取,GrabAttachMech为RotatorTrack

lamp脚本 抓取时忽视目标物理效果,放开时

灭火器钥匙抓取,沿线抓取(无节点),可用vrtk_Slider(见025control026 自动抓取和力破坏

移动

GameObject.renderer.enabled   
//是控制一个物体是否在屏幕上渲染或显示  而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的  

GameObject.Destroy()    
//表示移除物体或物体上的组件 代表销毁该物体  实际上该物体的内存并没有立即释放,而是等到这一帧的结束才会真正销毁

GameObject.SetActive()     
//是否在场景中停用该物体,设置gameObject.SetActive(false),则你在场景中用find找不到该物体    
//如果该物体有子物体 你要用SetActiveRecursively(false) 来控制是否在场景中停用该物体(递归的)
//SetActive(false)的时候,物体不再渲染,释放占用资源

Camera.cullingMask
//设置相机的渲染层次,在不需要某个物体的时候,cullingMask中将此物体的layer去掉,但是前提是要规划好layer,不能影响其他不希望隐藏掉的物体。

GameObject.transform.position = FAR_AWAY
//设置一个无限远的位置,再不需要的时候就将物体移动至这个位置,但是这样物体并没有释放,占用的所有资源都会继续占用


//开启关闭别的物品

            if (test_show.activeSelf == true)
                test_show.SetActive(false);
            else
                test_show.SetActive(true);

GameObj隐藏

前向移动
this.transform.Translate(Vector3.forward*Time.deltaTime*speed);

示例一个frefab,刚体化并施加力
GameObject ball =GameObject.Instantiate(ballprefab);
ball.name = "Ball " + nextBallNumber;
ball.transform.position = this.transform.position;
ball.transform.localScale = new Vector3 (0.2f, 0.24f, 0.2f);
ball.AddComponent<Rigidbody> ();
ball.GetComponent<Rigidbody>().mass=0.01f ;
ball.GetComponent<Rigidbody>().useGravity=false ;
ball.GetComponent<Rigidbody>().AddForce(new Vector3(0,50,0),ForceMode.Acceleration);

building例子

把手lever:
VRTK_LeverControl Reactor(go:deverdispaly),WaterControl(hose例子)

窗口上Windows_frame_set:
Fire_bigsmall

水管water hose:
可交互(fixed),有抓取点
下面hose_water_particles:My_hose1


CameraRig:
Steam VR_Controller Manager
steamVR Play Area
VRTKsimulator
手柄:
VRTK_交互、抓取、活动、事件
ControllerTooltip
GripTooltip

Mathf.MoveTowards 移向

static function MoveTowards (current : float, target : float, maxDelta : float) : float
Description描述
Moves a value current towards target.
改变一个当前值向目标值靠近。
This is essentially the same as Mathf.Lerp but instead the function will ensure that the speed never exceeds maxDelta. Negative values of maxDelta pushes the value away from target.
这实际上和 Mathf.Lerp相同,而是该函数将确保我们的速度不会超过maxDelta。maxDelta为负值将目标从推离。
C#
JavaScript
var target = 20.0;

var speed = 5.0;



function Update() {

    transform.position = Vector3(Mathf.MoveTowards

    (transform.position.x, target, speed * Time.deltaTime), 0, 0);

}

射线

在脚本中输入Vector3 fwd = transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(transform.position, fwd,out hit,1))
Debug.DrawLine(transform.position,hit.point,Color.red);
其中,Physics.Raycast(transform.position, fwd,out hit,1)为发射射线函数,transform.position为射线原点,fwd为发射方向,1为距离。
如果前方有碰撞体,则发射射线。

射线取点

Ray.GetPoint

public Vector3 GetPoint(float distance);
Description

Returns a point at distance units along the ray.

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
    public Ray r;
    void Example() {
        print(r.GetPoint(10));
    }
}

两点间移动

function Update () {
        transform.position = Vector3(Mathf.Lerp(minimum, maximum, Time.time), 0, 0);
}
lerp 就可以了     minimum 是你起始点, max是你到的点   你可以把 x y z 都换成 lerp  
transform.position = Vector3(Mathf.Lerp(minimum, maximum, Time.time), Mathf.Lerp(minimum, maximum, Time.time), Mathf.Lerp(minimum, maximum, Time.time));
就这样   再把起始点的 xyz 分别填入,终点的也填入  就可以了。
追问
谢谢解答,还有一个问题就是速度怎么控制呢
追答
Time.time   换成  Time.deltaTime   然后可以用 Time.deltaTime 乘以一个数

比如   
Time.deltaTime *2  或者  
Time.deltaTime * 0.1  

数越大速度越快

UI

1. 首先创建一个Canvas。然后将Canvas的Render Model设为WorldSpace
2. 将Canvas Scaler组件中的Dynamic  pixels Per Unit 适当调的大一点(过大好像 会影响性能)
,原因为这样可以提高该画布的单位动态像素的数量,可以解决UGUI文本模糊的问题。
3. 然后创建UI调整适当大小以及距离。
(若需要将UI更随头盔转动,则需要将Canvas  作为Camera(head)的子节点)

异步加载

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class LoadSlider : MonoBehaviour
{

    public Slider slider;
    public GameObject panel;
    private AsyncOperation async_operation;
    private bool load_switch;


    // Use this for initialization
    void Start ()
    {
        panel.SetActive (false);
        load_switch = false;
    }

    //显示加载进度
    void Update ()
    {
        if (load_switch) {
            slider.value = async_operation.progress;
        }
    }

    //根据输入名加载场景
    public void StartScene (string scene_name)
    {
        panel.SetActive (true);
        load_switch = true;
        StartCoroutine ("LoadScene", scene_name);
    }

    //异步加载场景
    IEnumerator LoadScene (string scene_name)
    {
        async_operation = SceneManager.LoadSceneAsync (scene_name);
        yield return async_operation;
    }
}

菜单界面生成

[Tooltip("菜单object拖入")]
    public GameObject menuObject;
    [Tooltip ("菜单界面生成距离")]
    public int MenuDistance = 3;
    GameObject eye;


    private void Start()
    {
        GetComponent<VRTK_ControllerEvents>().AliasMenuOn += new ControllerInteractionEventHandler(DoMenuOn);
    }



    private void DoMenuOn(object sender, ControllerInteractionEventArgs e)
    {
        if (menuObject.activeSelf == true)
            menuObject.SetActive(false);
        else
        {
            menuObject.SetActive(true);
            eye = GameObject.Find("Headset");
            Ray r=new Ray(eye.transform.position, eye.transform.forward);
            Vector3 fPoint= r.GetPoint(MenuDistance);

            //下一句旋转可行,但是三轴都转,容易转歪
            menuObject.transform.rotation = eye.transform.rotation;
            //下面将横滚角z值置零,以免界面随头部歪斜
            //面板中transform.rotation的更改赋值方法,由于类型是Quaternion,不能直接赋值
            Vector3 rotationtemp = menuObject.transform.localEulerAngles;
            rotationtemp.z = 0; // 在这里修改坐标轴的值
            menuObject.transform.localEulerAngles = rotationtemp;
            //位置定位            
            menuObject.transform.position = fPoint;
        }
    }

电梯上下移动

using UnityEngine;
using System.Collections;

public class dianti : MonoBehaviour {
    Transform oldTrans;
    public int UpSpeed = 1;//上升速度
    public int UpA = 1;
    public int DownSpeed = 10;//下降速度
    public int DownA = 1;
    bool DiantiUpPressed = true;
    bool StartJump = true;
    [Tooltip ("楼高")]
    public double lougao = 100;
    // Use this for initialization
    void Start () {
        oldTrans = this.transform;
    }

    // Update is called once per frame
    void Update () {
        DiantiUp();
    }
    /// <summary>
    /// 按键时电梯向上
    /// </summary>
    void DiantiUp() {

        if(DiantiUpPressed)
        { if (this.transform.position.y < lougao)
                this.transform.position += (new Vector3(0, 100, 0)) * Time.deltaTime * (UpSpeed * Time.deltaTime);
            else
                DiantiUpPressed = false;
         }
        else DiantiJump();


    }
    /// <summary>
    /// 电梯掉落
    /// </summary>
    void DiantiJump() {
        if (StartJump)
        { if(this.transform.position.y >0)
                //this.GetComponent<Rigidbody>().AddForce(0, -DownSpeed, 0, ForceMode.Acceleration);
                this.transform.position += (new Vector3(0, 1000, 0)) * Time.deltaTime * (-DownSpeed*Time.deltaTime);
            else
                //this.GetComponent<Rigidbody>().AddForce(0, 0, 0, ForceMode.VelocityChange);
                this.transform.position = oldTrans.position;
        }


    }

}

编辑器复制对象

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;



public class CopyObj : Editor {


        //  static public GameObject SelectedObj = new GameObject();
        static public int num = 25;
        [MenuItem("YxEditor/Copy #&C")]
        static void Copy()
        {
            //  CopyObj.SelectedObj = Selection.activeGameObject;

            for (int i = 1; i < num; i++)
            {
                GameObject obj;
                if (Selection.activeObject)
                {
                    obj = (GameObject)Instantiate(Selection.activeGameObject);
                    obj.transform.SetParent(Selection.activeGameObject.transform.parent);
                    obj.transform.position =Selection.activeGameObject.transform.position+ new Vector3(0.0f, 4.5f*i, 0.0f);
                }

            }

        }
    }

#

#

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值