2D中,随机一个位置产生物体(如:Sprite),而产生的这个物体能够被看到,那么这个物体就必须要生成在可视的范围中。
这个范围怎么确定呢?通过视口空间转变为世界坐标就行了。(0,0)表示相机视口的最下方,(1,1)表示相机视口的最上方。
Vector3 up = Camera.main.ViewportToWorldPoint(new Vector3(1, 1, 0)); Vector3 down = Camera.main.ViewportToWorldPoint(Vector3.zero);
那么x的范围为[down.x,up.x]
y的范围为[down.y,up.y]
不知道原因的,使用CaptureScreenshot不能保存到截图到安卓的文件系统中
所以使用另一种方式,成功了。
public IEnumerator CaptureScreenShow() { yield return new WaitForEndOfFrame(); string fileName = DateTime.Now.Ticks.ToString(); string tagerFolder = DateTime.Now.ToString("yyyy-MM-dd"); string pathName = Path.Combine(Application.persistentDataPath, tagerFolder); if (!Directory.Exists(pathName)) { Directory.CreateDirectory(pathName); } string path = pathName+"/"+fileName + ".png"; //Application.CaptureScreenshot(path); //截全屏,当然你可以控制大小 Texture2D t = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, true); t.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0, false); t.Apply(); byte[] byt = t.EncodeToPNG();//转换为字节 File.WriteAllBytes(path, byt);//保存到路径的文件中 yield return null; //判断是否截图成功 if (File.Exists(path)) { Debug.Log("截图成功!"); } else { Debug.Log("截图失败!"); } }
其实应该就是读取屏幕的像素保存到Texture中,然后将Texture保存到文件系统中。
读取屏幕的像素,应该是渲染完成后再读取,所以要先等待到帧结束时再读取保存。
void Update () { if (Input.GetKeyDown(KeyCode.C)) { string fileName = DateTime.Now.Ticks.ToString(); string tagerFolder = DateTime.Now.ToString("yyyy-MM-dd"); string pathName = Path.Combine(Application.persistentDataPath, tagerFolder); if (!Directory.Exists(pathName)) { Directory.CreateDirectory(pathName); } string path = Path.Combine(pathName, fileName + ".png"); //Application.CaptureScreenshot(path);Unity2017弃用了 ScreenCapture.CaptureScreenshot(path); Debug.Log(path); } }
如果不写路径只写文件名时,截图就会在保存在Unity工程的根目录中。
using UnityEngine; using System.Collections; using System.Diagnostics; using System; public class TestBatch : MonoBehaviour { // Use this for initialization void Start() { try { Process myProcess = new Process(); myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; myProcess.StartInfo.CreateNoWindow = true; myProcess.StartInfo.UseShellExecute = false; myProcess.StartInfo.FileName = "C:\\Windows\\system32\\cmd.exe"; string path = "C:\\Users\\Brian\\Desktop\\testFile.bat"; myProcess.StartInfo.Arguments = "/c" + path; myProcess.EnableRaisingEvents = true; myProcess.Start(); myProcess.WaitForExit(); int ExitCode = myProcess.ExitCode; //print(ExitCode); } catch (Exception e) { print(e); } } }
using UnityEngine; public class CameraFollow : MonoBehaviour { private Transform target; public float offsetY = 3f; public float offsetZ = 6f; public float speed = 10f; void Awake() { //默认跟随标签为Player的物体 target = GameObject.FindGameObjectWithTag("Player").transform; } public void SetTarget(Transform t) { target = t; } void LateUpdate() { if (target != null) { transform.LookAt(target); Vector3 tar = target.TransformPoint(0, offsetY, -offsetZ); transform.position = Vector3.Lerp(transform.position, tar,Time.deltaTime * speed); } } }
根据跟随目标,获取它向后面和上面的指定长度的世界位置,作为相机的滑动目标位置。
确保摄像机有Physics Raycaster组件
using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class testDrawLine : MonoBehaviour, IDragHandler, IEndDragHandler { public Color color = Color.red; public float thickness = 0.02f; private List<Vector3> points = new List<Vector3>(); private List<Vector3> normals = new List<Vector3>(); private List<int> splits = new List<int>();//分割索引 static Material lineMaterial; static void CreateLineMaterial() { if (!lineMaterial) { // Unity has a built-in shader that is useful for drawing // simple colored things. var shader = Shader.Find("Hidden/Internal-Colored"); lineMaterial = new Material(shader); lineMaterial.hideFlags = HideFlags.HideAndDontSave; // Turn on alpha blending lineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); // Turn backface culling off lineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off); // Turn off depth writes lineMaterial.SetInt("_ZWrite", 0); } } public void OnRenderObject() { CreateLineMaterial(); lineMaterial.SetPass(0); GL.PushMatrix(); GL.MultMatrix(transform.localToWorldMatrix); GL.Begin(GL.LINES); int index = 0; for (int i=1; i<points.Count; i++) { if (index < splits.Count && i == splits[index]){ index++; continue; } GL.Color(color); var from = points[i-1] + normals[i-1] * thickness; GL.Vertex3(from.x, from.y, from.z); var worldNormal = transform.TransformDirection(normals[i]); var to = points[i] + worldNormal * thickness; Debug.Log(worldNormal); GL.Vertex3(to.x, to.y, to.z); } GL.End(); GL.PopMatrix(); } public void OnBeginDrag(PointerEventData eventData) { } public void OnDrag(PointerEventData eventData) { if (!eventData.pointerCurrentRaycast.isValid) { SplitPoints(); return; } var localPosition = transform.InverseTransformPoint(eventData.pointerCurrentRaycast.worldPosition); points.Add(localPosition); var localNormal = transform.InverseTransformDirection(eventData.pointerCurrentRaycast.worldNormal); normals.Add(localNormal); } public void OnEndDrag(PointerEventData eventData) { SplitPoints(); } void SplitPoints() { if (splits.Count == 0 && points.Count != 0 || splits[splits.Count - 1] != points.Count) splits.Add(points.Count); } }
在3D物体上挂上这个组件脚本就可以用鼠标在物体上划线了。
using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; public class ScrollTest : MonoBehaviour,IBeginDragHandler,IEndDragHandler { //滚动内容 public RectTransform content; //填充类容单元 public GameObject image; //滚动脚本 public ScrollRect rect; //总共的单元个数 public int AllItemNum; //一页放多少个单元 public int PageItemNum; //总页数 private int PageNum; //一页的长度 private float peerPageLength; public float targer = 0; public bool isDrag = false; // Use this for initialization void Awake() { for (int i = 0; i < AllItemNum; i++) { GameObject go = Instantiate(image); go.transform.parent = content; } GridLayoutGroup g = content.GetComponent<GridLayoutGroup>(); //计算滚动内容的总水平长度,然后设置 float itemLength = g.cellSize.x + g.spacing.x; int PageRowNum = PageItemNum / g.constraintCount; float pageLength = itemLength * PageRowNum; PageNum = Mathf.CeilToInt( AllItemNum / PageItemNum) + 1; content.sizeDelta = new Vector2(pageLength * PageNum,content.sizeDelta.y); //计算一页的长度,19个,8个每页,共3页,就是0,0.5,13段 peerPageLength = 1f / (PageNum - 1); } // Update is called once per frame void Update () { if (isDrag) return; rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targer, Time.deltaTime * 30); } public void OnBeginDrag(PointerEventData eventData) { isDrag = true; } public void OnEndDrag(PointerEventData eventData) { isDrag = false; if (eventData.delta.x > 0f || targer < rect.horizontalNormalizedPosition) targer += peerPageLength; else { targer -= peerPageLength; } targer = Mathf.Clamp01(targer); } }
如果是在Unity中单单的用脚本类来封装Debug,添加一个全局控制的变量的话,是可以通过设置这个变量来解决Unity打包后不输出这些Debug。但是在Editor中双击输出日志就会定位到封装的Debug类中,就显然的就很不理想了。解决办法就是把这个封装的类变成dll文件后再导入。
一、dll文件的制作
新建dll类库项目,修改项目目标框架为.Net3.5,引入UnityEngine.dll(可以在Unity安装目录下搜索找到),然后新建public的类进行封装。
using UnityEngine; namespace DebugLog { public class DebugLog { public static DebugLog UI = new DebugLog("UI"); private string module; public bool IsOut = true; public DebugLog(string module) { this.module = module; } public void Log(string mes) { if(IsOut) Debug.Log(module+ ":" + mes); } } }
二、使用
将生成的dll拉进Unity项目中,使用这个类输出日志,具体的其他实际使用的细节就忽略了。
using UnityEngine; public class TestDebugLog : MonoBehaviour { void Start () { DebugLog.DebugLog.UI.Log("Hello"); DebugLog.DebugLog.UI.IsOut = false; DebugLog.DebugLog.UI.Log("world"); } }
只输出了前面的Hello,只要将IsOut的设置放在全部输出的前面,就可以实现控制了。
当然还可以自定义输出日志模块的文字样式等。
缺点就是,每次添加模块或则做一些修改,都需要重新生成dll,引入。
using System.Collections; using UnityEngine; using UnityEngine.Networking; public class Proc : MonoBehaviour { UnityWebRequest web; void Start () { StartCoroutine(WebDown()); } void Update () { if(web != null) Debug.Log(web.downloadProgress); } IEnumerator WebDown() { web = UnityWebRequest.Get("http://down.sandai.net/thunder9/Thunder9.1.47.1020.exe"); yield return web.SendWebRequest(); } }
以静态方法来获取下载的实例的,UnityWebRequest对网络操作都采取这种方式了
using System.Collections; using UnityEngine; public class Proc : MonoBehaviour { WWW www; void Start () { StartCoroutine(Down()); } void Update () { if(www != null) Debug.Log(www.progress); } IEnumerator Down() { www = new WWW("https://store.unity.com/cn/download/thank-you?thank-you=personal&os=win&nid=528"); yield return www; } }
当然,下载进度其实是对大型文件才有用处的,不然只能看到0直接变成1了。