zoukankan      html  css  js  c++  java
  • Unity3D学习笔记(十):Physics类和射线

    物理系统:碰撞器、触发器等
    力:有大小有方向的矢量,有受力点位置(和向量的区别)
    ----F = ma(m质量,a加速度,质量越大,加速度越小,停下来越慢)
    ----m1v1 = m2v2(冲量守恒定理,质量越小,速度越快)
    ----力的分解
    Ft = mv(动量定理)
    ----Rigid.AddForce(Vector3.forward, ForceMode mode);写在Start里
    ----Force(默认):持续力,完全满足动量守恒定理;Ft = mv
    ----Impulse:瞬间冲击力、爆炸力,不完全满足动量守恒定理;忽略t,让t = 1,F = mv
    ----VelocityChange:直接改变速度;忽略t和m,让t = m = 1,F =v
    ----Acceleration:给一个加速度;忽略m,让m = 1,Ft =v
    力矩:作用力使物体绕着转动轴或支点转动的趋向。
    ----Rigid.AddTorque(Vector3.up);
    练习:Dota2的选人面板,人物可以拖拽旋转,速度越来越快,反向拖动,转速大幅降低
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class ForceTest : MonoBehaviour {
        public float forceFactor = 10;
        private Rigidbody rigid;
        private float mouse_x;
        // Use this for initialization
        void Start () {
            //力需要一个目标,只有非运动学刚体才会收到力的影响
            rigid = GetComponent<Rigidbody>();
            //力的单位1牛顿,质量0.1KG
            //ForceMode是枚举,
            //rigid.AddForce(Vector3.forward,ForceMode.Impulse);
            //rigid.AddForceAtPosition(Vector3.forward,new Vector3(1,1,1));
            //rigid.AddTorque(Vector3.up);
          
            //最大旋转速度,限制物体旋转速度,可以修改
            rigid.maxAngularVelocity = 999999;
          
        }
        // Update is called once per frame
        void Update () {
            //练习:Dota2的选人面板,人物可以拖拽旋转,速度越来越快,反向拖动,转速大幅降低
            //按下鼠标左键拖动才会接收值      
            if (Input.GetMouseButton(0))
            {
                mouse_x = Input.GetAxis("Mouse X");
            }
            else
            {
                mouse_x = 0;
            }
            rigid.AddTorque(Vector3.up * -mouse_x * forceFactor, ForceMode.Force);
            //鼠标当前帧的位置可以获取,和上一帧相减,可以得到一个旋转的偏移量
            //Input.mousePosition
        }
    }
    力给在物体重心上
    rigid.AddForce(Vector3.forward,ForceMode.Impulse);
    选一个受力点,添加一个力,可以让物体旋转起来
    rigid.AddForceAtPosition(Vector3.forward,new Vector3(1,1,1));
    Physics - Gravity,方向向下的重力

    ForceMode是枚举

    直线:向两端无限延长的直的线,没有端点
    线段:两个点之间的直线,两个端点
    射线:由一个点向一个方向发射一条无限延长的直线,一个端点
    Unity如何判断前方扇形面积有敌人
    Ray Unity中的射线(结构体),有两个参数,origin原点,direction方向
    射线检测的唯一条件:游戏物体必须有碰撞器组件,有没有刚体无所谓
    layerMask层级遮罩,设置只检查哪一个层级的游戏物体,默认全部检测
    RaycastHit hitInfo是碰撞信息
    bool : Physics.Raycast(Ray ray, float maxDistance, int layerMask, QueryTriggerInteraction queryTriggerInteraction);
    RaycastHit[] hitinfos = Physics.RaycastAll();
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class RaycastTest : MonoBehaviour {
        private Ray ray;
        private RaycastHit hitInfo;
        // Use this for initialization
        void Start () {
            //层级位移运算
            int layerMask = (1 << 8);
            Debug.Log(layerMask);
            layerMask = (1 << 9);
            Debug.Log(layerMask);
            layerMask = (1 << 8) | (1 << 9);
            Debug.Log(layerMask);
            layerMask = LayerMask.GetMask(new string[] { "Lxm", "Cjy" });
            Debug.Log(layerMask);
            //结果第8位,第9位
            //Ray(Vector3 origin, Vector3 direction);
            //Ray射线是结构体,有两个参数,origin原点,direction方向
            ray = new Ray(transform.position,Vector3.forward);
            //发射射线,物理系统的光线投射,有16种重载
            //Physics.Raycast(ray);
            //射线是没有网格的,是看不到,是物理系统的一部分,是数学计算得来的
            if (Physics.Raycast(ray))
            {
                Debug.Log("射线已射中物体");
            }
            //maxDistance射线的最大距离就是float的最大值,可以手动设置
            //Raycast(Ray ray, float maxDistance);
            //hitinfo:这条射线所碰撞物体的相关信息,储存碰撞物体的信息;
            //Raycast(Ray ray, out RaycastHit hitInfo);
            if (Physics.Raycast(ray, out hitInfo, 100, layerMask, QueryTriggerInteraction.Ignore))
            {
                Debug.Log(hitInfo.transform.name);
                Debug.DrawLine(transform.position, hitInfo.point,Color.red,100);
            }
            //层级遮罩,设置只检查哪一个层级的游戏物体,默认全部检测
            //层级实质相当于枚举项,值是2的幂次方,序号只是层级的索引
            //Raycast(Ray ray, float maxDistance, int layerMask);
            //如果检测第八层,需要填写256
            if (Physics.Raycast(ray, collider.gameObject.tag, 256))
            {
                Debug.Log(hitInfo.transform.name);
                Debug.DrawLine(transform.position, hitInfo.point, Color.red, 100);
            }
            //Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);
            //Ray ray是射线;RaycastHit hitInfo是碰撞信息;float distance是碰撞距离;int layerMask是碰撞的层
            //RaycastAll穿过多个物体
            RaycastHit[] hitinfos = Physics.RaycastAll(ray,100);
            foreach (var item in hitinfos)
            {
                Debug.Log(item.transform.name);
            }
            //不仅发射摄像,还可以发射形状物体
            //Physics.BoxCast();
            //Physics.CapsuleCast();
            //如何检测一个人在地面上而不是在空中(二段跳判定)
            //1、在人物半身添加一个向下的射线,射线刚好接触地面
            //2、在人物头顶添加一个投射盒
            //特点:
            //射线是一帧判定
            //射线没有运行时间
            //位运算符(二进制的加减乘除)
            //&与运算:有零即为零,全一才是一
            //1001010
            //1000111  &
            //-----------
            //1000010
            //|或运算:有一就是一,全零才是零
            //1001010
            //1110001   |
            //-----------
            //1111011
            //~非运算符:一变零,零变一
            //1101010  ~
            //-----------
            //1111011
            //^异或运算:相同即为零,不同即为一
            //1010001
            //1100010   ^
            //-----------
            //0110011
            //<<向左移:所有二进制位向高位进位,空出来的位补零
            //1010<<1
            //-----------
            //10100
            //>>向右移:所有二进制位向低位进位,移出位被丢弃,左边移出的空位或者一律补0
            //1011>>1
            //-----------
            //0101
        }
        // Update is called once per frame
        void Update () {
                  
           }
    }
    相交球:
    Collider[] OverlapSphere(Vector3 position, float radius);
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class BoomScript : MonoBehaviour {
       
        public float forceFactor = 10;
    
    
        private void OnCollisionEnter(Collision collision)
        {
            //生成橡胶球,检测碰撞
            Collider[] colliders = Physics.OverlapSphere(transform.position, 10);
            //剔除自己和没有加刚体的
            foreach (var item in colliders)
            {
                //剔除自己
                if (item.transform == transform)
                {
                    continue;
                }
                //判断刚体不等于空,防止与地面碰撞
                //attachedRigidbody,碰撞器附加的刚体,如果碰撞器没有附加刚体返回null。
                if (item.attachedRigidbody != null)
                {
                    float distance = Vector3.Distance(transform.position, item.transform.position);
                    float forceValue = 1 / distance * forceFactor;
                    Vector3 dir = (item.transform.position - transform.position).normalized;
                    Vector3 force = dir * forceValue;
                    item.attachedRigidbody.AddForce(force, ForceMode.Impulse);
                }
            }
        }
    }

    Line Renderer

    线体渲染,添加颜色,Line Renderer 配合 ray射线 可以制作镭射激光
    用材质球渲染射线,粒子特效
    Width曲线,调节粗细,添加关键帧,调节线体不同部位的粗细
    画复杂线段,多点添加
    设置颜色的渐变
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class PlayerFire : MonoBehaviour {
        LineRenderer lineR;
        public Transform fireTrans;
        //方便对layer作调节
        public LayerMask layer;
        Ray ray;
        RaycastHit hit;
           void Start () {
            lineR = GetComponent<LineRenderer>();
        }
           
           void Update () {
            ray = new Ray(fireTrans.position, fireTrans.up);
            if(Physics.Raycast(ray, out hit, 1000, layer))
            {
                //hit.point
                lineR.positionCount = 2;
                lineR.SetPosition(0, fireTrans.position);
                lineR.SetPosition(1, hit.point);
            }
            else
            {
                lineR.positionCount = 0;
            }
           }
    }
    C#的委托和事件在Unity中的用法
    委托 - Action:没有返回值,没有参数的,在using System命名空间下
    带一个参数,没有返回值的委托怎么定义,public Action<float> OnValueChanged
    委托变事件,直接加event
    通过滑动条Value的变化,来调用委托
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System;
    public class DeleTest : MonoBehaviour
    {
        public float width = 100;
        public float height = 50;
        public event Action buttonClickCallback;
        public event Action<float> OnValueChanged;  // 事件 用来封装委托的
        private float floatValue;
        public float FloatValue
        {
            get
            {
                return floatValue;
            }
            set
            {
                if (value != floatValue)
                {
                    // 触发事件
                    if (OnValueChanged != null) OnValueChanged(value);
                }
                floatValue = value;
            }
        }
        public float size = 1;
        public GUIStyle sliderStyle;
        public GUIStyle thumbStyle;
        void Start()
        {
            FloatValue = 100;
        }
        void Update()
        {
        }
        private void OnGUI()
        {
            if (GUI.Button(new Rect((Screen.width - width) / 2, (Screen.height - height) / 2, width, height), "开始游戏"))
            {
                if (buttonClickCallback != null) buttonClickCallback();
            }
            //  public static float Slider(Rect position, float value, float size, float start, float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id);
            //value = GUI.Slider(new Rect(10, 10, width, height), value, size, 0, 10, sliderStyle, thumbStyle, true, 0);
        }
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class Test : MonoBehaviour {
           void Awake () {
            DeleTest del = GetComponent<DeleTest>();
            del.buttonClickCallback += SceneChange;
            del.OnValueChanged += MusicValueChange;
            //del.OnValueChanged();
        }
           
           void Update () {
                  
           }
        void SceneChange()
        {
            Debug.Log("切换场景啦!!!!");
        }
        void MusicValueChange(float value)
        {
            Debug.Log("音量调节为了:" +value);
        }
    }
  • 相关阅读:
    撩课-Web大前端每天5道面试题-Day15
    撩课-Web大前端每天5道面试题-Day14
    撩课-Java每天5道面试题第26天
    撩课-Java每天5道面试题第25天
    撩课-Web大前端每天5道面试题-Day13
    撩课-Java每天5道面试题第24天
    撩课-每天刷Web面试题(前10天汇总)-Day12
    撩课-Java每天5道面试题第23天
    撩课-Web大前端每天5道面试题-Day11
    java设计模式-策略模式
  • 原文地址:https://www.cnblogs.com/vuciao/p/10362902.html
Copyright © 2011-2022 走看看