检查是否是2的整数幂

苹果手机, 图片长宽均为2的整数幂, 且是正方形, 才能用pvrtc4压缩
检查图片是否为POT:

static bool IsPowerOfTwo(int x)
{return x > 0 && (x & (x - 1)) == 0;
}
或者
static bool IsPowerOfTwo(int x)
{return (x & -x) == x;
}

原理看这里: https://stackoverflow.com/questions/600293/how-to-check-if-a-number-is-a-power-of-2

新手引导: 射线穿透

新手引导, 遮罩镂空, 整个遮罩不可点击, 只有镂空处能点击

把这个脚本挂在全屏遮罩上

public class RayCastHollow : MonoBehaviour, ICanvasRaycastFilter
{public RectTransform rect; //镂空图片bool ICanvasRaycastFilter.IsRaycastLocationValid(Vector2 screenPos, Camera eventCamera){// 将镂空图范围内的事件镂空return !RectTransformUtility.RectangleContainsScreenPoint(rect, screenPos, eventCamera);}
}

点击2D精灵图的射线检测

本来用的是3D盒子碰撞体做的, 但这样做有个问题: 点空白区域的时候, 会触发检测
由于2D的Sprite没法用MashCollider, 所以用PolygonCollider2D
此处有个坑点: PolygonCollider2D只能站着, 不能平躺下, 所以相机必须以Z轴为正方向, 不能用Y轴

2D的射线检测和3D不一样, 要用Physics2D.Raycast, 不用Ray

 void Update(){if (Input.GetMouseButtonDown(0)){Vector3 mousePos = Input.mousePosition;mousePos.z = -Camera.main.transform.localPosition.z;Vector3 worldPos = Camera.main.ScreenToWorldPoint(mousePos);RaycastHit2D hit = Physics2D.Raycast(worldPos, Vector2.zero);if (hit.transform != null){print(hit.transform.name);}}}

知道方向向量, 计算角度

2d游戏, Vector3.up为前方向, 不能用LookAt或者LookRotation
已知从我指向敌人的方向向量, 计算子弹的rotation

计算角度, 角度小于90度则是向前发射, 大于90度则是向后发射
点乘, 看敌人在我的左边还是右边
用Quaternion.Euler设置角度, 只需旋转Z轴即可

-- dir是从我指向敌人的方向向量
function SetRot(dir)-- 夹角必定小于180local angle = Vector3.Angle(Vector3.up, dir)local dot = Vector3.Dot(Vector3.right, dir)-- dot>0, 说明往左发射, 所以角度为负数if dot > 0 thenangle = -angleendtransform.rotation = Quaternion.Euler(Vector3(0, 0, angle))
end

递归深度查找子孙

    public static GameObject FindChild(GameObject parent, string childName){if (parent.name == childName){return parent;}if (parent.transform.childCount < 1){return null;}GameObject obj = null;for (int i = 0; i < parent.transform.childCount; i++){GameObject go = parent.transform.GetChild(i).gameObject;obj = FindChild(go, childName);if (obj != null){break;}}return obj;}

第一人称视角, 键盘控制移动, 鼠标控制视角

直接拿去挂在相机上就能跑了

using UnityEngine;public class FPS : MonoBehaviour
{float moveSpeed = 1;Vector3 moveDir = Vector3.zero;float rotSpeed = 50;Vector3 rotDir = Vector3.zero;float minY = -45;float maxY = 45;void Update(){Move();Rot();}private void Move(){moveDir.x = Input.GetAxis("Horizontal");moveDir.z = Input.GetAxis("Vertical");transform.Translate(moveDir * Time.deltaTime * moveSpeed, Space.Self);}private void Rot(){rotDir.y += Input.GetAxis("Mouse X") * Time.deltaTime * rotSpeed;rotDir.x -= Input.GetAxis("Mouse Y") * Time.deltaTime * rotSpeed;rotDir.x = Mathf.Clamp(rotDir.x, minY, maxY);transform.localEulerAngles = rotDir;}
}

按顺序更换地图:

  1. 每打4局更换地图
  2. 按顺序更换3张地图
  3. 显示剩余局数

lua代码:

interval = 4
map = {1, 2, 3}
for playCount = 0, 13 dolocal index = playCount // interval % #map + 1local remain = interval - playCount % intervalprint('当前地图为: ' .. map[index] .. '   剩余刷新数: ' .. remain)
end输出:
当前地图为: 1   剩余刷新数: 4
当前地图为: 1   剩余刷新数: 3
当前地图为: 1   剩余刷新数: 2
当前地图为: 1   剩余刷新数: 1
当前地图为: 2   剩余刷新数: 4
当前地图为: 2   剩余刷新数: 3
当前地图为: 2   剩余刷新数: 2
当前地图为: 2   剩余刷新数: 1
当前地图为: 3   剩余刷新数: 4
当前地图为: 3   剩余刷新数: 3
当前地图为: 3   剩余刷新数: 2
当前地图为: 3   剩余刷新数: 1
当前地图为: 1   剩余刷新数: 4
当前地图为: 1   剩余刷新数: 3

随机问题:

规则:

  1. 权重比为 a: b: c = 3: 4: 3
  2. 不一定abc都有, 可能会没有a, 也可能会没有c, 也可能会没有bc, 也可能一个都没有
  3. 按权重, 随机取一个

以下是伪代码
我的方法:

x = a ? 3 : 0
y = b ? 4 : 0
z = c ? 3 : 0
-- 放一堆小球进袋子
for x { all.add(q1) }
for y { all.add(q2) }
for z { all.add(q3) }
-- 从袋子里拿出一个
r = random( all.count )
if all[r] == q1   --> a
if all[r] == q2   --> b
if all[r] == q3   --> c

同事的方法:

x = a ? 3 : 0
y = b ? 4 : 0
z = c ? 3 : 0
-- 这一步是精髓, 分段
all[3] = { x, x+y, x+y+z }
r = random( x+y+z )
i = 0
for i<all.count, i++
{-- 看随机数落在哪个段里if r<all[i]break
}
if i == 0   --> a
if i == 1   --> b
if i == 2   --> c

RSA加密解密

公钥密钥可以去https://www.bejson.com/enc/rsa/自己生一个

public class Web : MonoBehaviour
{public static string publicKey = "";public static string privateKey = "";void Start(){CreateKeys(out privateKey, out publicKey);string passwordOriginal = "123456";string passswordEncrypt = RSAEncrypt(passwordOriginal);Debug.LogError("加密后的密码为: " + passswordEncrypt);string passwordDecrypt = RSADecrypt(passswordEncrypt);Debug.LogError("解密后的密码为: " + passwordDecrypt);}//生成Xml形式的Keypublic static void CreateKeys(out string PrivateKey, out string PublicKey){try{RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();PrivateKey = rsa.ToXmlString(true);//true是包含公钥和私钥PublicKey = rsa.ToXmlString(false);//false是只包含公钥}catch (Exception ex){throw ex;}}//解密public static string RSADecrypt(string content){RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();rsa.FromXmlString(privateKey);byte[] cipherbytes = rsa.Decrypt(Convert.FromBase64String(content), false);return Encoding.UTF8.GetString(cipherbytes);}//加密public static string RSAEncrypt(string content){RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();rsa.FromXmlString(publicKey);byte[] cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);return Convert.ToBase64String(cipherbytes);}
}

数据改变通知

继承 INotifyPropertyChanged

using System.ComponentModel;
using System.Runtime.CompilerServices;class NotifyObject : INotifyPropertyChanged{private int number1;public int Number1{get { return number1; }set{if (number1 != value){number1 = value;OnPropertyChanged();}}}//private int number2;//private int number3;public event PropertyChangedEventHandler PropertyChanged;//[CallerMemberName]的作用:自动添加属性名protected void OnPropertyChanged([CallerMemberName] string propertyName = ""){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}

PropertyChanged += Do, 就能在属性改变时执行Do方法

    void Do(object sender, PropertyChangedEventArgs property){switch (property.PropertyName){case "Number1":Debug.LogError(1);break;case "Number2":Debug.LogError(2);break;}}

很详细的文章, 甚至写了泛型:
https://www.cnblogs.com/TianFang/p/3381484.html

序号同步移动

需求是这样的:
17个问题, 对应17个小灯, 能显示红色或绿色来判断回答的正误, 17个小灯横着排列在屏幕上方;
因为17个都排出来不好看, 所以用了Scroll View只显示9个;
小灯要跟着我的答题序号同步移动, 比如我答第8题, 第8个小灯要居中显示;
后面有可能还要加更多题, 不止17个题.

 //先把灯显示出来, 不管是17个还是1万个private void InitJudgeLight(){judgeLightsList = new List<JudgeLight>();for (int i = 0; i < Data.allQuestionsList.Count; i++){JudgeLight judge = Instantiate(Resources.Load<JudgeLight>("Prefabs/ChildJudgeLight"), parentJudgeLight);judgeLightsList.Add(judge);//数字显示为i+1Text[] texts = judge.transform.GetComponentsInChildren<Text>(true);Array.ConvertAll(texts, p => p.text = (i + 1).ToString());}}//答题的时候, 小灯移动public void ShowQuestion(){//更新bar, 4 表示前5个题不用动, 9 是一共只能显示9个题int nowQues = Data.GetCurrentQuestionIndex() - 4;//小于0也没关系的//需移动的次数 = 灯总数 - 灯显示数, 比如说共有10个题, 框内仅能显示8个, 即需要移动2次int maxQues = Data.allQuestionsList.Count - 9;barJudgeLight.value = (float)nowQues / maxQues;...//后面写显示问题}

↓后面又加了些动画

    public void ShowQuestion(){int nowQues = Data.GetCurrentQuestionIndex() - 4;int maxQues = Data.allQuestionsList.Count - 9;//滚动条会往前挪动一下DOTween.To(() => barJudgeLight.value, x => barJudgeLight.value = x, (float)nowQues / maxQues, 1f).SetEase(Ease.OutBack);//当前正在回答的问题会呼吸int index = Data.GetCurrentQuestionIndex();tweenJudgeLight = judgeLightsList[index].transform.DOScale(1.1f, 0.5f).SetLoops(-1, LoopType.Yoyo);...//后面写显示问题}

额, 如果太多了就不要全加载出来了, 如果太多就写个循环显示, 网上很多, 一搜就有;

简单的相机Lerp跟随

当人物快跑时, 镜头会被拉远, 会有"跑太快, 镜头都跟不上了"的感觉
太近了的话有可能会穿模, 所以相机的最近距离给个0.01;

using UnityEngine;public class LerpFlollow : MonoBehaviour
{public Transform target;private Vector3 offset;public float moveSpeed;void Start(){offset = transform.position - target.position;}void Update(){transform.position = Vector3.Lerp(transform.position, target.position + offset, Time.deltaTime * moveSpeed);}
}

UI图标闪烁

主要是Mathf.PingPong(value, max);
会从0到max, 以value增加的速度, 做来回运动

using UnityEngine;
using UnityEngine.UI;public class ImageSparkle : MonoBehaviour
{private Image image;private void Start(){image = GetComponent<Image>();}private void Update(){//回头看看, 这里的Color应该做一个全局的, 不要每帧都newimage.color = new Color(1, 0, 0, Mathf.PingPong(Time.time, 1));}private void OnDestroy(){image.color = new Color(0, 0, 0, 0);}
}

↓要完善的话再加上这一堆东西

     public static ImageSparkle Get<T>(T t) where T : Component{ImageSparkle sparkle = t.gameObject.GetComponent<ImageSparkle>();if (sparkle == null){sparkle = t.gameObject.AddComponent<ImageSparkle>();}return sparkle;}public static ImageSparkle Get(GameObject obj){ImageSparkle sparkle = obj.GetComponent<ImageSparkle>();if (sparkle == null){sparkle = obj.AddComponent<ImageSparkle>();}return sparkle;}public static void Remove(GameObject obj){ImageSparkle sparkle = obj.GetComponent<ImageSparkle>();if (sparkle != null){Destroy(sparkle);}}

更简单的方法是用DOTween, 但是如果多次激活这个方法的话就不大好用了

image.DOFade(0,1).SetLoops(-1,LoopType.Yoyo);

搜索工具栏

主要是 InputField.onValueChanged.AddListener();

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class SearchTool : MonoBehaviour
{private List<GameObject> toolsList;public InputField input;private void Awake(){input.onValueChanged.AddListener(str => Scerch(str));toolsList = new List<GameObject>();foreach (Transform item in transform){toolsList.Add(item.gameObject);}}private void Scerch(string str){for (int i = 0; i < toolsList.Count; i++){toolsList[i].SetActive(false);}List<GameObject> resultsList = toolsList.FindAll(p => p.name.Contains(str));for (int i = 0; i < resultsList.Count; i++){resultsList[i].SetActive(true);}}
}

↓改了一版, 节省掉了2个遍历1个列表

 private void ScerchTools(string str){for (int i = 0; i < toolsList.Count; i++){GameObject tool = toolsList[i];if (tool.name.Contains(str)){tool.SetActive(true);}else{tool.SetActive(false);}}}

↓甚至可以简化成这样 (但没必要, 因为别人可能不好理解, 也不便于修改)

 private void ScerchTools(string str){toolsList.ForEach(p => p.SetActive(p.name.Contains(str)));}

按钮控制Scroll View(这里只用Horizontal Scroll Bar)

如果不希望"鼠标可以在View里拖动View", 那就把Scroll Rect上的Horizontal取消勾选;

using UnityEngine;
using UnityEngine.UI;public class SliderCtrl : MonoBehaviour
{public Scrollbar bar;public Button btnRight;public Button btnLeft;private void Awake(){btnRight.onClick.AddListener(() => clickBtnRight());btnLeft.onClick.AddListener(() => clickBtnLeft());}private void clickBtnRight(){bar.value += 0.5f;}private void clickBtnLeft(){bar.value -= 0.5f;}
}

鼠标滑轮控制视野(带有平滑效果)

主要是用的Mathf.Lerp();

 private float nextView;private float nowView = 60;private float minView = 12;private float maxView = 80;private void Update(){if (cameraOutUI.activeInHierarchy){float speed = Input.GetAxis("Mouse ScrollWheel");//当在滑if (Mathf.Abs(speed) > Mathf.Abs(nextView)){nextView = speed;}//减速到0nextView = Mathf.Lerp(nextView, 0, 5 * Time.deltaTime);//乘法改变viewnowView *= (1 - nextView * 0.15f);nowView = Mathf.Clamp(nowView, minView, maxView);//限制视野camera.fieldOfView = nowView;}}

镜头随鼠标轻微转动

用的是eulerAngles
FPSController是身体, 只负责绕Y轴转动
FPSHead是头(相机), 挂在身体上, 只负责绕X轴转动

    /// <summary>/// 禁用第一人称的时候, 我觉得静止的镜头很无聊, 就加了镜头随鼠标轻微转动/// </summary>private void CameraRotateLittle(){if (!isFPS){//当鼠标左右滑动的时候, 我们希望视角是绕Y轴旋转的float rotY = Mathf.Clamp(FPSController.eulerAngles.y + Input.GetAxis("Mouse X") * Time.deltaTime, 120, 150);FPSController.eulerAngles = new Vector3(0, rotY, 0);//当鼠标上下滑动的时候, 我们希望视角是绕X轴旋转的, 注意这里↓是减法float rotX = Mathf.Clamp(FPSHead.localEulerAngles.x - Input.GetAxis("Mouse Y") * Time.deltaTime, 5, 30);FPSHead.localEulerAngles = new Vector3(rotX, 0, 0);}}

需要注意的是eulerAngles.x只能是0到180的值, 不能为负数

用图片的fillAmount实现渐隐渐出效果

精髓是: 等下一帧 yield return new WaitForEndOfFrame();

public IEnumerator ShowChoosePanel()
{float filledNum = 0;while (filledNum < 1){filledNum += Time.deltaTime;imageFill.fillAmount = filledNum;yield return new WaitForEndOfFrame();}
}

注意: 写while的时候, 要么像上面↑这样在循环内有延时, 要么像下面↓这样保证能够跳出循环

while (a < 10)
{a++;
}
//或者
while (true)
{a++;if(a >= 10) return;
}

如果写成下面↓这样, 编辑器会卡死

while (true){}

模型展示

按住鼠标右键控制上下左右旋转, 滑轮放大缩小

if (Input.GetMouseButton(1))
{bagPos.Rotate(new Vector3(Input.GetAxis("Mouse Y")*2, -Input.GetAxis("Mouse X"))*2, Space.World);
}
if (Input.GetAxis("Mouse ScrollWheel") != 0)
{bagPos.position -= Vector3.forward * Input.GetAxis("Mouse ScrollWheel") * 50;//限制放大bagPos.localPosition = new Vector3(bagPos.localPosition.x, bagPos.localPosition.y, Mathf.Clamp(bagPos.localPosition.z, -300, 0));
}

禁用鼠标

//禁用鼠标
Cursor.lockState = CursorLockMode.Locked;//锁定鼠标, 禁止鼠标移动到游戏窗口以外
Cursor.visible = false;//鼠标不可见(仅在游戏窗口内), 如果鼠标移动到游戏视窗外, 鼠标还是可见的
//启用鼠标
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;

更改鼠标图标

API是这样的:
public static void SetCursor(Texture2D texture, Vector2 hotspot, CursorMode cursorMode);
参数1是鼠标样式图, 参数2是点击响应点, 一般是(0,0), 即左上角, 参数3选Auto//用法
Cursor.SetCursor(normalCursor, new Vector2(0, 0), CursorMode.Auto);
//鼠标图的中心点
Cursor.SetCursor(normalCursor, normalCursor.texelSize / 2, CursorMode.Auto);

洗牌算法

    public static void RandomList<T>(List<T> list){for (int i = 0; i < list.Count; i++){int randomIndex = UnityEngine.Random.Range(i, list.Count);T temp = list[i];list[i] = list[randomIndex];list[randomIndex] = temp;}}

Unity实现一些小功能(持续更新)相关推荐

  1. Unity3D小功能 小技巧 小教程 小原理(持续更新...)

    Unity3D小功能 小技巧 小教程 小原理(持续更新...) 1.Unity的.NET版本是2.0 按道理来说,C#能用的功能Unity也能用,但是Unity的.NET却不是最新版 要是用一些别的D ...

  2. Unity游戏优化指南大全(持续更新中!)

    Unity游戏优化指南大全 三个官方优化提示: 性能和优化 (Performance and Optimization) - 关于性能分析器以及性能和优化技巧的 Unity 学习教程. Best pr ...

  3. Android实用小技巧(持续更新)

    文章目录 给drawableRight设置点击事件 限制EditText可输入的字数,超出后提示文案 解决RecycleView布局中GridLayoutManager和StaggeredGridLa ...

  4. 小白使用word小技巧-持续更新(以论文服务为主)

    文章目录 写论文时的记录,本人键盘各位置图,仅供参考(事实上,使用word,按一下Alt,可以看到word屏幕上的快捷键提示,记不住就对着按就行了) 1.文字快捷键 : 2.文本的段落样式设置快捷键和 ...

  5. android 模拟器 vuforia,Vuforia+Unity尝试AR小功能(1)

    本人新手菜鸟,看了网上很多教程,希望把它记录下来作为自己的回顾和总结.本文纯属自娱自乐,如有大神请帮忙指点一下,蟹蟹- 配置环境 首先需要安装Unity软件,到官网下载安装文件,在安装过程中记得勾选i ...

  6. Unity 2020 By Example 笔记(持续更新中)

    第一款游戏中,玩家将以第一人称控制一个角色去探索一个环境,并在时间限制结束前收集硬币.如果计时器超时,游戏就结束了.另一方面,如果玩家在计时器到期前收集到所有的硬币,那么他就赢了.控制将使用工业标准的 ...

  7. ASP.NET 开发小技巧 (持续更新)

    有时为一些小问题而去查资料.浪费太多的时间,为此把开发中经常遇到的一些小问题.记录下来.供日常开发查询用: 1.项目中使用Forms验证.而有些文件又不需要验证就能访问,最常见的是验证码文件或admi ...

  8. golang 小知识-持续更新中

    Golang 中的指针 - Pointer Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,ar ...

  9. Python日常小技巧(持续更新中)

    目录 快速定位元组内容 对字典进行排序 json的获取(dumps,dump,loads,load) 查找字典中相同的key 统计列表中元素的个数 字典按输入顺序输出 历史记录的存储 对有多个分割符的 ...

最新文章

  1. gcc 编译 java,编译lineage,gcc的版本问题
  2. TCP连接管理【三次握手-四次挥手】
  3. 抢占大数据产业发展先机
  4. Android 程序启动界面Demo
  5. 设计模式解析笔记之Adapter模式
  6. shields 徽标_符号,标志,文字标记:徽标类型的综合指南
  7. java异常 字节码,Java字节码角度分析异常处理
  8. android收入管理系统,毕业设计(论文)-基于Android系统的家庭理财通软件的设计——收入管理模块.docx...
  9. word 代码块_如何优雅的写好 Pythonic 代码?
  10. 消息中间件学习总结(6)——RocketMQ之RocketMQ大数据畅想
  11. 三星中文AI助手Bixby发布,现在,这是“一家AI商用技术公司”
  12. [LintCode] Swap Nodes in Pairs
  13. VB-ocx应用于Web
  14. matlab浪漫画图,Matlab技巧11:谁说数学人不懂浪漫——Matlab画隐函数曲面
  15. W3Cschool离线文档
  16. 51单片机数码管中断倒计时报警
  17. Android NDK SO库隐藏内部符号表
  18. VTK笔记-图形相关-两个平面上的多边形+三角带=闭合多边形(棱柱体)
  19. Anaconda详细安装及使用教程
  20. 工作站 显卡 测试软件,绝对专业!14块工作站显卡测试(图)

热门文章

  1. Arduino+sim800C家居安防火灾报警 拨打电话 发送短信例程程序
  2. C语言实现二路归并算法
  3. 施工员培训建筑八大员培训施工员建筑桩基工程施工技术的要点
  4. 梦幻诛仙linux系统游戏,梦幻诛仙_网络游戏专区_腾讯游戏频道
  5. Win7 3264位纯净版下载地址
  6. 吃多少唐僧才能长生不老? (转载)
  7. 游戏建模师很抢手吗?
  8. NGUI动态字体的使用
  9. 织梦模板php代码诸城房,Thinkphp开源房产程序源码(多城市版房产系统+带手机版模板)...
  10. 温度检测-GPU温度(1)