////////////////////////////////////////
销毁关联的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
- 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
- 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)
using UnityEngine;
using CoroutineTest;
public class Init : MonoBehaviour {
void Awake () {
MyClass API = new MyClass();
API.startRoutine();
}
}
MyClass.cs (inside CoroutineTest.dll)
using System;
using System.Collections;
using UnityEngine;
namespace CoroutineTest
{
public class MyClass : MonoBehaviour
{
public MyClass ()
{
}
public void startRoutine()
{
Log.debug("calling routine");
StartCoroutine(myRoutine());
}
private IEnumerator myRoutine()
{
Log.debug("routine started");
yield return new WaitForSeconds(1.0F);
Log.debug("routine finished");
}
}
}
Log output
calling routine
NullReferenceException
at (wrapper managed-to-native) UnityEngine.MonoBehaviour:StartCoroutine_Auto (System.Collections.IEnumerator)
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:
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.
public class Init : MonoBehaviour{
void Awake () {
MyClass API = gameObject.AddComponent<MyClass>();
API.startRoutine();
}
}
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处理 #############
- Enemy_AI.js
- private var Regression : Vector3;
- public var Player_Prefab : Transform;
- public var Enemy_State : String;
- public var Doing : boolean = true;
- public var Range : float = 4.0;
- public var Bullet : Transform;
- public var Bullet_Prefab : Transform;
- //初始化敌人方向和位置
- function Start()
- {
- transform.localEulerAngles.y = Random.value * 360;
- Regression = transform.position;
- }
- //敌人行动模式
- public var Thinking : boolean = true;
- public var Thinking_Time : float = 1.0;
- private var relativePos : Vector3;
- private var rotation : Quaternion;
- public var Facing : boolean = false;
- public var Facing_Time : float = 2.0;
- public var Facing_Speed : float = 2.0;
- public var Moving : boolean = false;
- public var Moving_Speed : float = 0.5;
- public var Moving_Time : float = 4.0;
- public var Moving_Back : boolean = false;
- public var Attacking : boolean = false;
- private var Bullet_DO : boolean = true;
- public var Bullet_CD : float = 0.2;
- //随机移动方位
- private var R_Position : Vector3;
- function Update ()
- {
- if(Attacking)
- {
- Enemy_State = "Attacking";
- Facing = true;
- Moving = true;
- //Doing = true;
- Thinking = false;
- var dist2 = Vector3.Distance(Regression, transform.position);
- if(dist2 > 20)
- {
- relativePos = Regression - transform.position;
- rotation = Quaternion.LookRotation(relativePos);
- Attacking = false;
- Moving_Back = true;
- }
- }
- if(!Moving_Back)
- {
- var dist = Vector3.Distance(Player_Prefab.position, transform.position);
- if(dist > 100)
- {
- Attacking = false;
- return;
- }
- else if(dist < 5)
- {
- Attacking = true;
- }
- RayJudge();
- }
- transform.localEulerAngles.x = 0;
- transform.localEulerAngles.z = 0;
- if(Thinking && !Attacking && !Moving_Back)
- {
- Enemy_State = "Thinking";
- if(Doing)
- {
- StartCoroutine(Think(Thinking_Time));
- Doing = false;
- }
- }
- if(Facing)
- {
- Enemy_State = "Facing";
- if(Attacking)
- {
- relativePos = Player_Prefab.position - transform.position;
- rotation = Quaternion.LookRotation(relativePos);
- transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * Facing_Speed * 4);
- }
- else if(Moving_Back)
- {
- transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * Facing_Speed * 4);
- }
- else
- {
- transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * Facing_Speed);
- if(Doing)
- {
- StartCoroutine(Face(Facing_Time));
- Doing = false;
- }
- }
- }
- if(Moving)
- {
- Enemy_State = "Moving";
- if(Moving_Back)
- {
- transform.Translate(Vector3.forward * Time.deltaTime * Moving_Speed * 6);
- }
- else if(dist > 2)
- {
- if(Attacking)
- {
- transform.Translate(Vector3.forward * Time.deltaTime * Moving_Speed * 4);
- }
- else
- {
- transform.Translate(Vector3.forward * Time.deltaTime * Moving_Speed);
- }
- }
- if(Doing && !Attacking)
- {
- StartCoroutine(Move(Moving_Time));
- Doing = false;
- }
- }
- }
- //前方锁敌
- function RayJudge()
- {
- var layerMask = 1 << 2;
- layerMask = ~layerMask;
- var hit : RaycastHit;
- if(Physics.Raycast (transform.position, transform.TransformDirection(Vector3.forward), hit, 20,layerMask))
- {
- var distanceToForward = hit.distance;
- if(hit.transform.tag == "Player")
- {
- Attacking = true;
- if(Bullet_DO)
- {
- var Create = Instantiate (Bullet_Prefab, Bullet.position, Quaternion.identity);
- Create.rigidbody.AddForce (Bullet.forward * 1000);
- StartCoroutine(Wait(Bullet_CD));
- Bullet_DO = false;
- }
- }
- }
- }
- function Wait(waitTime : float)
- {
- yield WaitForSeconds (waitTime);
- Bullet_DO = true;
- }
- function Move(waitTime : float)
- {
- print("Move");
- if(Moving_Back)
- {
- yield WaitForSeconds (waitTime * 0.4);
- }
- else
- {
- yield WaitForSeconds (waitTime + Random.value * 2);
- }
- Thinking = true;
- Moving_Back = false;
- Moving = false;
- Facing = false;
- Doing = true;
- }
- function Face(waitTime : float)
- {
- print("Face");
- yield WaitForSeconds (waitTime + Random.value);
- Facing = false;
- Thinking = false;
- Moving = true;
- Doing = true;
- }
- function Think(waitTime : float)
- {
- print("Thinking");
- yield WaitForSeconds (waitTime + Random.value);
- R_Position = Regression + Random.insideUnitSphere * Range;
- R_Position.y = Regression.y;
- relativePos = R_Position - transform.position;
- rotation = Quaternion.LookRotation(relativePos);
- Thinking = false;
- Moving = false;
- Facing = true;
- 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;
}
}
//##################################################################################
//##############################
//################################################################
#