Unity中3D一些使用方法代码2015(为自己)

本文介绍了Unity3D中的一些高级技巧,包括模型导入、物体旋转、屏幕截图、协程使用、角色跟随摄像机、简单的AI行为实现等。还探讨了如何销毁关联的MonoBehaviour、位掩码的使用、内存管理等技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

////////////////////////////////////////

销毁关联的MonoBehaviour或它的父GameObject。禁用MonoBehaviour或GameObject都不会停止InvokeRepeating()。

///////////////////////////////////////////

导入fbx model的时候

AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Models/scar_h.fbx");

  Mesh m = (Mesh)AssetDatabase.LoadAssetAtPath("Assets/Models/scar_h.fbx", typeof(Mesh));
 GameObject Go = new GameObject();
 Go.AddComponent<MeshFilter>();
 Go.AddComponent<MeshRenderer>();
 Go.GetComponent<MeshFilter>().mesh = m;
 Go.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f);
 Go.transform.position = new Vector3(0, 0, 2);

////////////////////////////////////////////////////////////////

Samples~ .github 这样的文件夹名字 不在Asset里显示

var rect = m_EffectArea.GetEffectArea(vh, rectTransform.rect);

            // rotation.
            var rad = m_Rotation * Mathf.Deg2Rad;
            var dir = new Vector2(Mathf.Cos(rad), Mathf.Sin(rad));
            dir.x *= rect.height / rect.width;
            dir = dir.normalized;

            // Calculate vertex position.
            var vertex = default(UIVertex);
            var localMatrix = new Matrix2x3(rect, dir.x, dir.y); // Get

var player = serializedObject.FindProperty("m_Player");
            _spPlay = player.FindPropertyRelative("play");
            _spDuration = player.FindPropertyRelative("duration");

//////////////////////////////////////////////////////////////////

// Bit shift the index of the layer (8) to get a bit mask
    int layerMask = 1 << 8;
        
    // This would cast rays only against colliders in layer 8.
    // But instead we want to collide against everything except layer 8. The ~ operator does this, it inverts a bitmask.
    layerMask = ~layerMask;

cullingMask is stored as bit mask. First bit (i.e. (1 << 0) or simply 1) represenst first layer. Sencond bit (i.e. (1 << 1) or simply 2) represent second layer. Third bit (i.e. (1 << 2) or simply 4) represent third layer. And so on. When you want to have two layers active you combine their appropriate bits with | operator. For example I need fist and fourth layer, so my mask would be ((1 << 0) | (1 << 3)) = (1 | 8) = 9

物体XZ平面旋转夹角的方法

float angle = Vector3.Angle (fromVector,toVector); //求出两向量之间的夹角

Vector3 normal = Vector3.Cross(fromVector,toVector);//叉乘求出法线向量

angle *= Mathf.Sign(Vector3.Dot(normal,upVector));  //求法线向量与物体上方向向量点乘,结果为1或-1,修正旋转方向

Vector3 velocity = Quaternion.Inverse(transform.rotation)*destinationVector; //对目标向量进行反向旋转,得到的新向量与z轴的夹角即为目标向量与当前物体方向的夹角             

float angle = Mathf.Atan2(velocity.x,velocity.z) * Mathf.Rad2Deg; //返回tan值为x/z的角的弧度,再转化为度数。

float VectorAngle(Vector2 from, Vector2 to)

    {

       float angle;

      

       Vector3 cross=Vector3.Cross(from, to);

       angle = Vector2.Angle(from, to);

       return cross.z > 0 ? -angle : angle;

}

         public Transform a;

         public Transform b;

         void Start()

         {

                   float dot =Vector3.Dot(a.transform.forward, b.transform.forward);

                   float angle = Mathf.Acos(dot)* Mathf.Rad2Deg;

                   //如果想打印角度,取消注释即可

                   //print(angle);

         }

System.GC.Collect();
Resources.UnloadUnusedAssets();

System.GC.Collect() will tell .Net collector to collect objects which are managed by mono in the managed heap, while Resources.UnloadUnusedAssets deals with assets (textures, sounds and other media) which are put in the native heap. The two method do totally different things, so there is no different which one will be executed first. (As you said, they are both async and you just set a flag to suggest the system it could be a good time to do a collect.)

In fact, it is not so common to call GC collect yourself, except you have a good reason. The GC of system will work in proper time, most of calling for forcing a garbage collect are not so necessary as you think.

物体的平滑旋转

float ver = 0;
    float hor = 0;
    public float turnspeed = 10;
    
    // Update is called once per frame  
    void Update()
    {
        hor = Input.GetAxis("Horizontal");
        ver = Input.GetAxis("Vertical");
    }
    void Rotating(float hor, float ver)
    {
        //获取方向  
        Vector3 dir = new Vector3(hor, 0, ver);
        //将方向转换为四元数  
        Quaternion quaDir = Quaternion.LookRotation(dir, Vector3.up);
        //缓慢转动到目标点  
        transform.rotation = Quaternion.Lerp(transform.rotation, quaDir, Time.fixedDeltaTime * turnspeed);
    }


    void FixedUpdate()
    {
        if (hor != 0 || ver != 0)
        {
            //转身  
            Rotating(hor, ver);
        }
    }

1,让一个物体围绕某一点旋转,有几种方法?分别是什么?

答:在这个点处放一个空物体B,则问题变为A绕着B旋转,

方法1:B不动,A挂脚本实现transform的RotateAround(vector3 point, vector3 axis, float angle)函数

例如 A.RotateAround(B.position, Vector3.up,  30*Time.deltaTime);   //A绕着B的y轴进行旋转。

方法2:A不动,A作为B的子物体,B挂脚本实现自转,然后带着A转,类似于模拟围绕中心天体旋转。

例如:B.Rotate (Vector3.up, 30*Time.deltaTime, Space.Self); //B绕着自身的up方向自转,从而带着A一起转。

方法3:矩阵变换,研究中。       

注:旋转的常用方法:

(1)绕坐标轴旋转

[csharp] view plain copy

  1. public void Rotate (Vector3 eulerAngles, Space relativeTo = Space.Self);  

或者

public void Rotate (float xAngle, float yAngle, float zAngleSpace, relativeTo = Space.Self);

其中relativeTo = Space.Self表示绕自身坐标系旋转,ralativeTo = Space.World表示绕世界坐标系旋转。

(2)饶某个向量旋转

public void Rotate(Vector3 axis, float angle, Space relativeTo);

其中axis为旋转轴方向,angle为旋转角度,relativeTo为参考坐标系,默认为Space.self。此方法的功能是使得GameObject对象在relativeTo坐标系中绕轴向量axis旋转angle度。

(3)绕轴点旋转

[csharp] view plain copy

  1. public void RotateAround(Vector3 point, Vector3 axis, float angel);  

功能是使得GameObject对象绕着point点的axis方向旋转angle度。

截图

private const float SCREEN_SHOT_WIDTH = 400;


    private static ScreenShotUtil mInstance;


    private static string mPicturePath;


    public Camera captureCamera;


    void Awake()
    {
        mInstance = this;


        // 获取对应平台的可访问路径
        mPicturePath = Application.persistentDataPath + "/screenshot.png";
    }


    public static void Shot()
    {
        mInstance.TackCapture();
    }


    /// <summary>
    /// 截屏操作
    /// </summary>
    private void TackCapture()
    {
        float tempScale = SCREEN_SHOT_WIDTH / Screen.width;
        StartCoroutine(CaptureCamera(captureCamera, new Rect(0, 0, Screen.width * tempScale, Screen.height * tempScale), mPicturePath));
    }


    IEnumerator CaptureCamera(Camera camera, Rect rect, string imgPath)
    {
        yield return new WaitForEndOfFrame();
        // 创建一个RenderTexture对象
        RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 24);
        // 临时设置相关相机的targetTexture为rt, 并手动渲染相关相机
        camera.targetTexture = rt;
        camera.Render();
        yield return new WaitForEndOfFrame();


        // 激活这个rt, 并从中中读取像素。
        RenderTexture.active = rt;
        Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
        screenShot.ReadPixels(rect, 0, 0);// 注:这个时候,它是从RenderTexture.active中读取像素
        screenShot.Apply();
        // 重置相关参数,以使用camera继续在屏幕上显示
        camera.targetTexture = null;
        RenderTexture.active = null; // JC: added to avoid errors
        GameObject.Destroy(rt);
        yield return new WaitForEndOfFrame();


        // 最后将这些纹理数据,成一个png图片文件
        byte[] bytes = screenShot.EncodeToPNG();
        string filename = imgPath;
        File.WriteAllBytes(filename, bytes);


        SDKUtils.ShowToast(filename);
    }


    public static string GetPicturePath()
    {
        return mPicturePath;
    }

//其他类的StartCoroutine

Init.cs (attached to a game object)

 
  1. using UnityEngine;
  2. using CoroutineTest;
  3. public class Init : MonoBehaviour {
  4. void Awake () {
  5. MyClass API = new MyClass();
  6. API.startRoutine();
  7. }
  8. }

MyClass.cs (inside CoroutineTest.dll)

 
  1. using System;
  2. using System.Collections;
  3. using UnityEngine;
  4. namespace CoroutineTest
  5. {
  6. public class MyClass : MonoBehaviour
  7. {
  8. public MyClass ()
  9. {
  10. }
  11. public void startRoutine()
  12. {
  13. Log.debug("calling routine");
  14. StartCoroutine(myRoutine());
  15. }
  16. private IEnumerator myRoutine()
  17. {
  18. Log.debug("routine started");
  19. yield return new WaitForSeconds(1.0F);
  20. Log.debug("routine finished");
  21. }
  22. }
  23. }

Log output

calling routine

 
  1. NullReferenceException
  2. at (wrapper managed-to-native) UnityEngine.MonoBehaviour:StartCoroutine_Auto (System.Collections.IEnumerator)
  3. at UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine) [0x00000] in <filename unknown>:0

 it should be ok to use coroutines in dlls as long as you inherit from MonoBehaviour. But you've done something else wrong:

 
  1. MyClass API = new MyClass();

Never ever create a MonoBehaviour with new, that won't work. MonoBehaviours are Components and can only exist on GameObjects. Use AddComponent to add your behaviour to an GameObject and you should be fine.

 
  1. public class Init : MonoBehaviour{
  2. void Awake () {
  3. MyClass API = gameObject.AddComponent<MyClass>();
  4. API.startRoutine();
  5. }
  6. }

Unity 3D场景中的模型 和 角色名字保持相对位置

using UnityEngine;
using System.Collections;

public class NamePanel : MonoBehaviour
{
    [SerializeField]
    UILabel lblName;

    [SerializeField]
    GameObject obj;

    [SerializeField]
    Camera mainCamera;

    [SerializeField]
    Camera uiCamera;

    void Update()
    {
        UpdateNamePosition();
    }

    Vector3 m_position;
    /// <summary>
    /// 更新名字位置
    /// </summary>
    void UpdateNamePosition()
    {
        //取模型在主摄像机中的世界坐标
        m_position = obj.transform.position;
        //转换为主摄像机的屏幕坐标
        m_position = mainCamera.WorldToScreenPoint(m_position);
        //用得到的屏幕坐标,在UI摄像机中转换为世界坐标
        m_position = uiCamera.ScreenToWorldPoint(m_position);
        m_position.z = 0f;
        m_position.y += 0.1f;
        lblName.transform.position = m_position;
    }
}

给摄像机添加一个Look At Target脚本,并将其Target设为人物。
接着自己写一个脚本Camera Round,拖给摄像机,让摄像机绕着人物旋转。
using UnityEngine;
using System.Collections;
public class cameraRound : MonoBehaviour {
       public GameObject hero;
        void Update () {
        gameObject.transform.RotateAround(hero.transform.position,Vector3.up,0.1f);
        }
}

using UnityEngine;
using System.Collections;
public class blood_bar : MonoBehaviour {
        public GameObject _bloodBar;//获取血条信息。
        public GameObject MainCamera;//获取主摄像机        
        void Update () {
                _bloodBar.transform.position=new Vector3(transform.position.x,transform.position.y+2.0f,transform.position.z);//让血条信息一直处于人物的头顶某处
                Vector3 v=transform.position-MainCamera.transform.position;
                Quaternion rotation;
                rotation = Quaternion.LookRotation(v);
                _bloodBar.transform.rotation = rotation;//让血条一直面向摄像机。由于摄像机是以人物为目标的,所以v应该为人物的位置到摄像机位置的向量,否则信息栏会出现偏差。
        }
}

//################## 简单的AI处理 #############

  1. Enemy_AI.js 
  2.  
  3. private var Regression : Vector3; 
  4. public var Player_Prefab : Transform; 
  5. public var Enemy_State : String; 
  6. public var Doing : boolean = true
  7. public var Range : float = 4.0
  8. public var Bullet : Transform; 
  9. public var Bullet_Prefab : Transform; 
  10. //初始化敌人方向和位置 
  11. function Start() 
  12. transform.localEulerAngles.y = Random.value * 360
  13. Regression = transform.position; 
  14. //敌人行动模式 
  15. public var Thinking : boolean = true
  16. public var Thinking_Time : float = 1.0
  17. private var relativePos : Vector3; 
  18. private var rotation : Quaternion; 
  19. public var Facing : boolean = false
  20. public var Facing_Time : float  = 2.0
  21. public var Facing_Speed : float = 2.0
  22. public var Moving : boolean = false
  23. public var Moving_Speed : float = 0.5
  24. public var Moving_Time : float = 4.0
  25. public var Moving_Back : boolean = false
  26. public var Attacking : boolean = false
  27. private var Bullet_DO : boolean = true
  28. public var Bullet_CD : float = 0.2
  29. //随机移动方位 
  30. private var R_Position : Vector3; 
  31. function Update () 
  32. if(Attacking) 
  33. Enemy_State = "Attacking"
  34. Facing = true
  35. Moving = true
  36. //Doing = true; 
  37. Thinking = false
  38. var dist2 = Vector3.Distance(Regression, transform.position); 
  39. if(dist2 > 20
  40. relativePos = Regression - transform.position; 
  41. rotation = Quaternion.LookRotation(relativePos); 
  42. Attacking = false
  43. Moving_Back = true
  44. if(!Moving_Back) 
  45. var dist = Vector3.Distance(Player_Prefab.position, transform.position); 
  46. if(dist > 100
  47. Attacking = false
  48. return
  49. else if(dist < 5
  50. Attacking = true
  51. RayJudge(); 
  52. transform.localEulerAngles.x = 0
  53. transform.localEulerAngles.z = 0
  54. if(Thinking && !Attacking && !Moving_Back) 
  55. Enemy_State = "Thinking"
  56. if(Doing) 
  57. StartCoroutine(Think(Thinking_Time)); 
  58. Doing = false
  59. if(Facing) 
  60. Enemy_State = "Facing"
  61. if(Attacking) 
  62. relativePos = Player_Prefab.position - transform.position; 
  63. rotation = Quaternion.LookRotation(relativePos); 
  64. transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * Facing_Speed * 4); 
  65. else if(Moving_Back) 
  66. transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * Facing_Speed * 4); 
  67. else 
  68. transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * Facing_Speed); 
  69. if(Doing) 
  70. StartCoroutine(Face(Facing_Time)); 
  71. Doing = false
  72. if(Moving) 
  73. Enemy_State = "Moving"
  74. if(Moving_Back) 
  75. transform.Translate(Vector3.forward * Time.deltaTime * Moving_Speed * 6); 
  76. else if(dist > 2
  77. if(Attacking) 
  78. transform.Translate(Vector3.forward * Time.deltaTime * Moving_Speed * 4); 
  79. else 
  80. transform.Translate(Vector3.forward * Time.deltaTime * Moving_Speed); 
  81. if(Doing && !Attacking) 
  82. StartCoroutine(Move(Moving_Time)); 
  83. Doing = false
  84. //前方锁敌 
  85. function RayJudge() 
  86. var layerMask = 1 << 2
  87. layerMask = ~layerMask; 
  88. var hit : RaycastHit; 
  89. if(Physics.Raycast (transform.position, transform.TransformDirection(Vector3.forward), hit, 20,layerMask)) 
  90. var distanceToForward = hit.distance; 
  91. if(hit.transform.tag == "Player"
  92. Attacking = true
  93. if(Bullet_DO) 
  94. var Create = Instantiate (Bullet_Prefab, Bullet.position, Quaternion.identity); 
  95. Create.rigidbody.AddForce (Bullet.forward * 1000); 
  96. StartCoroutine(Wait(Bullet_CD)); 
  97. Bullet_DO = false
  98. function Wait(waitTime : float
  99. yield WaitForSeconds (waitTime); 
  100. Bullet_DO = true
  101. function Move(waitTime : float
  102. print("Move"); 
  103. if(Moving_Back) 
  104. yield WaitForSeconds (waitTime * 0.4); 
  105. else 
  106. yield WaitForSeconds (waitTime + Random.value * 2); 
  107. Thinking = true
  108. Moving_Back = false
  109. Moving = false
  110. Facing = false
  111. Doing = true
  112. function Face(waitTime : float
  113. print("Face"); 
  114. yield WaitForSeconds (waitTime + Random.value); 
  115. Facing = false
  116. Thinking = false
  117. Moving = true
  118. Doing = true
  119. function Think(waitTime : float
  120. print("Thinking"); 
  121. yield WaitForSeconds (waitTime + Random.value); 
  122. R_Position = Regression + Random.insideUnitSphere * Range; 
  123. R_Position.y = Regression.y; 
  124. relativePos = R_Position - transform.position; 
  125. rotation = Quaternion.LookRotation(relativePos); 
  126. Thinking = false
  127. Moving = false
  128. Facing = true
  129. Doing = true

//#############################

//#################### 射线点击 实现鼠标控制 旋转和移动 #######################

private bool flagMove;
    private RaycastHit hit;
    private Vector3 mousePos;
    private Vector3 targetDir;
    // Use this for initialization 
    void Start()
    { flagMove = false; }
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        { RayControl(); }
        if (flagMove)
        {
            if (Vector3.Distance(transform.position, mousePos) > 0.1)
            { transform.Translate(transform.worldToLocalMatrix * transform.right * Time.deltaTime * 0.5f); }
            else
            {
                flagMove = false;
            }
        }
    }
    void RayControl()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//从Camera发射射线到屏幕 
        if (Physics.Raycast(ray, out hit))//射线碰撞检测
        {
            mousePos = hit.point;
            mousePos.z = transform.position.z;
            targetDir = mousePos - transform.position;//计算到目标点的方向 
            Vector3 tempDir = Vector3.Cross(transform.right, targetDir.normalized);
            float dotValue = Vector3.Dot(transform.right, targetDir.normalized);
            float angle = Mathf.Acos(dotValue) * Mathf.Rad2Deg;//计算夹角
            if (tempDir.z < 0)//根据叉乘判断夹角的正负
            { angle = angle * (-1); }
            if (!float.IsNaN(angle))
            {
                transform.RotateAround(transform.position, Vector3.forward, angle);//转向目标点 
            }
            flagMove = true;
        }
    }

//##################################################################################

//##############################  

//################################################################

#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值