山寨小小军团开发笔记 之 Arrow Projectile
好久没怎么更新博客了,今天抽空来一篇,讨论一下弓箭的轨迹生成。
一、原理
弓箭的轨迹本质就是一个数学问题,使用一个 bezier 曲线公式就可以插值生成。得到轨迹后,做一个lookAt就可以了。
二、Bezier 曲线原理
2015-5-15 :相关原理介绍,我就不重复了
http://zh.wikipedia.org/wiki/%E8%B2%9D%E8%8C%B2%E6%9B%B2%E7%B7%9A
http://devres.zoomquiet.io/data/20110728232822/index.html
我这里贴一下应用代码
public class Bezier
{
public Vector3 p0 = Vector3.zero;
public Vector3 p1 = Vector3.zero;
public Vector3 p2 = Vector3.zero; public Bezier(Vector3 v0, Vector3 v1, Vector3 v2)
{
this.p0 = v0;
this.p1 = v1;
this.p2 = v2;
} public void UpdateTargetPos(Vector3 v2)
{
p2 = v2;
} public Vector3 GetPointAtTime(float t)
{
float x = (1 - t) * (1 - t) * p0.x + 2 * t * (1 - t) * p1.x + t * t * p2.x;
float y = (1 - t) * (1 - t) * p0.y + 2 * t * (1 - t) * p1.y + t * t * p2.y;
float z = (1 - t) * (1 - t) * p0.z + 2 * t * (1 - t) * p1.z + t * t * p2.z;
return new Vector3(x, y, z);
}
}
三、例子分析
搭建一个测试场景,从中心点发射弓箭诡异
Center上挂载一个脚本
BezierTest.cs
public GameObject arrowPrefab; public Transform left; public Transform right; void Test(bool fireRight)
{
Transform end = fireRight ? right : left; ///在中心点生成弓箭
GameObject curArrow = arrowPool.Spawn(transform.position, Quaternion.Euler(Vector3.zero)); ///计算LookTarget的点 与 贝塞尔曲线的第三个控制点
Vector3[] points = Re_LookTarget_MiddlePerpendicularPoint(curArrow.transform, end); ///初始化发射
ArrowControl arrowControl = curArrow.GetComponent<ArrowControl>();
arrowControl.Init(
points[0],
points[1],
end.position,
3.0f,
delegate()
{
arrowPool.Unspawn(curArrow);
});
} Vector3[] Re_LookTarget_MiddlePerpendicularPoint(Transform self, Transform enemy)
{
Vector3 direction = (enemy.position - self.position).normalized; float segment = Vector2.Distance(enemy.position, self.position) / 2.0f; Vector3 lookTarget = (self.position + enemy.position) / 2.0f; Vector3 perpendicular_direction;
if (direction.x > 0)
{
perpendicular_direction = new Vector3(-direction.y, direction.x, 0);
}
else
{
perpendicular_direction = new Vector3(direction.y, -direction.x, 0);
} ///perpendicular line
Vector3 middle_pendicular = lookTarget + perpendicular_direction * segment; return new Vector3[] { lookTarget, middle_pendicular };
} void OnGUI()
{
if (GUI.Button(new Rect(10, 10, 150, 100), "Fire Left")) Test(false);
if (GUI.Button(new Rect(160, 10, 150, 100), "Fire Right")) Test(true);
}
预设上挂载的控制脚本
ArrowControl.cs
float alltimer; Util.Bezier bezier = null; float timer = 0f; Callback recycleFunction; Vector3 lookAtTarget; //bool defaultRightNeedTurn = false;; public void Init(Vector3 lookAtTarget, Vector3 middle, Vector3 end, float alltimer, Callback recycleFunction)
{
this.lookAtTarget = lookAtTarget; this.bezier = new Util.Bezier(transform.position, middle, end); this.alltimer = alltimer; Flip(end.x, transform.position.x); this.recycleFunction = recycleFunction;
} void Flip(float end_X, float self_X)
{
Transform pic = transform.Find("pic"); if (end_X < self_X) {
pic.localScale = new Vector3(-1.0f, 1.0f, 1.0f);
}
else {
pic.localScale = new Vector3( 1.0f, 1.0f, 1.0f);
}
} public void Clear()
{
this.bezier = null; timer = 0f;
} void Update()
{
if (this.bezier != null)
{
timer += Time.deltaTime; float t = timer / alltimer; //Debug.Log("timer" + timer + " t " + t); if (t >= 1.0f) { Clear(); if (recycleFunction != null) recycleFunction(); }
else {
transform.LookAt(lookAtTarget, Vector3.forward); transform.position = bezier.GetPointAtTime(t);
} }
}
这里注意,对于LookAt这个行为,我没有很好的数学方法,所以用了U3D的API。
但是这个API 只能保证Z轴始终指向target, 所以图片的旋转预先是这样。
四、结果
山寨小小军团开发笔记 之 Arrow Projectile的更多相关文章
- 山寨小小军团开发笔记 之 GamePool
很多时候我们对于物体(比如弓箭)大量的生成与销毁,这个时候可以把弓箭放在内存池中进行管理,加快体验.自己Copy了一个简易版的. 一.代码 GameObjectPoolManager.cs using ...
- ES6学习笔记<二>arrow functions 箭头函数、template string、destructuring
接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...
- [开发笔记]-未找到与约束ContractName Microsoft.VisualStudio.Text.ITextDocumentFactoryService...匹配的导出【转载自:酷小孩】
原文地址:http://www.cnblogs.com/babycool/p/3199158.html 今天打算用VisualStudio2012做一个js效果页面测试的时候,打开VS2012新建项目 ...
- EasyUI 开发笔记(二)
接上篇 :EasyUI 开发笔记(一) (http://www.cnblogs.com/yiayi/p/3485258.html) 这期就简单介绍下, easyui 的 list 展示, 在easy ...
- EasyUI 开发笔记(一)
由于某些原因,在公司做的后台需要改成类似于Ext.js 形式的后台,主要看好其中的 框架布局,以及tab开页面和弹出式内部窗体. 后来看看,改成EasyUI,较Ext.js 库小很多,也便于公司的初级 ...
- [Openwrt 项目开发笔记]:Openwrt平台搭建(一)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 最近开始着手进行Openwrt平台的物联网网关设 ...
- Android移动APP开发笔记——Cordova(PhoneGap)通过CordovaPlugin插件调用 Activity 实例
引言 Cordova(PhoneGap)采用的是HTML5+JavaScript混合模式来开发移动手机APP,因此当页面需要获取手机内部某些信息时(例如:联系人信息,坐标定位,短信等),程序就需要调用 ...
- Android移动APP开发笔记——最新版Cordova 5.3.1(PhoneGap)搭建开发环境
引言 简单介绍一下Cordova的来历,Cordova的前身叫PhoneGap,自被Adobe收购后交由Apache管理,并将其核心功能开源改名为Cordova.它能让你使用HTML5轻松调用本地AP ...
- 开发笔记:基于EntityFramework.Extended用EF实现指定字段的更新
今天在将一个项目中使用存储过程的遗留代码迁移至新的架构时,遇到了一个问题——如何用EF实现数据库中指定字段的更新(根据UserId更新Users表中的FaceUrl与AvatarUrl字段)? 原先调 ...
随机推荐
- StreamWriter和StremReader简单的用法
string str = "中国";//写入的内容 string path = @"e:\1.txt";//文件路径 StreamWriter sw = new ...
- css笔记——关于css中写上charset “utf-8”
当css文件中写上 charset "utf-8" 时需要将body和html的样式分开写 例如: html,body{margin:0;padding:0;font-family ...
- IPv6协议介绍
IPv6是为了解决基于IPv4的TCP/IP协议簇遇到的问题而推出的下一代IP协议.由于IPv4中采用的编制方式使得可用的网络地址和主机地址的数目远低于理论数目,随着全球互联网的快速发展,现有的IPv ...
- 开始进入Windows Phone 8开发
和大家一起分享从零开始,入手Windows Phone 8开发,大家一起来吧!
- 安装WordPress详细教程指南
最近准备自己建一个个人博客,以便分享一些自己工作生活中的一些观点及经验,建博客当然选wordpress,毕竟wordpress是为博客而生的嘛.下边记录一下自己安装WordPress的详细过程指南,亦 ...
- VmodCAM 初始化
; WIP Last Changed Rev: 2172 ;********************************************************************** ...
- tp中让头疼似懂非懂的create
项目中多次用到create() 只能它是表单验证,不过好出错,痛下心扉好好了解理解它的来龙去脉和所用的用法 一:通过create() 方法或者 赋值的方法生成数据对象,然后写入数据库 $model = ...
- 转:Android studio Gradle
提高Android Studio中Gradle执行效率 分类: android studio2015-06-26 11:54 2374人阅读 评论(2) 收藏 举报 android studiogra ...
- 《Java核心技术与最佳实践》读书笔记
第一章 Java7新语法 1.switch中使用字符串 2.增加二进制表示0b10101010:数字字面量允许直径使用下划线12_34_90 3.一个catch字句捕获多个异常,多个异常之间用|分隔 ...
- Ubuntu16.04.1 安装Redis-Cluster
Redis在3.0版正式引入了集群这个特性.Redis集群是一个分布式(distributed).容错(fault-tolerant)的 Redis内存K/V服务, 集群可以使用的功能是普通单机 Re ...