链接:https://www.zhihu.com/question/23757906/answer/25616658
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
其实GoF的《设计模式》一书,一共有三个层面的内容:
1. 指出编程开发活动中存在模式,提出总结设计模式需要关注的四要素 "名称-问题-解决方案-效果“ ,并给出描述一套模式的格式模板。
2. 提出了面向对象开发中”针对接口编程优于针对实现编程”,”组合优于继承”的总体设计思路
3. 选取了现实开发中基于上述设计思路所形成的23种常见设计模式作为例子详细描述
虽然第3点包括的多个具体的设计模式实例占据了最多的篇幅,但事实上第1,2点才是纲。实际上《设计模式》一书最划时代的意义,在于第1点。在此之后,出现了以设计模式的格式来组织内容的《分析模式》,《企业架构模式》,《企业集成模式》,《xUnit测试模式》,《重构》等等质量颇高的书籍
在书中有一段我认为非常重要但很容易被忽略的话
本书中涉及的设计模式并不描述新的或未经证实的设计,我们只收录那些在不同系统中多次使用过的成功设计。这些设计的绝大部分以往并无文本记录,它们或是来源于面向对象设计者圈子里的非正式交流,或是来源于某些成功的面向对象系统的某些部分,但对设计新手来说,这些东西是很难学得到的。尽管这些设计不包括新的思路,但我们用一种新的、便于理解的方式将其展现给读者,即:具有统一格式的、已分类编目的若干组设计模式。
这段话的关键是:
1. 书中的模式不是作者的发明创造或独门秘籍,而是早已存在并已经广泛使用的做法,只不过没有被系统地加以记录。换而言之,只要遵循某些原则,这些所谓模式完全可能在无意识的状态下自发出现在产品代码中。
2. 这些模式在各种系统被多次使用。换而言之,你只要接触足够多的代码,必然会大量接触到这些模式的实际应用。只不过在看过《设计模式》一书之前,你可能意识不到这是一个成体系的设计手段。
3. 作者认为《设计模式》这本书的价值在于对设计模式进行了有效的组织和便于理解的描述。换而言之,这本书的写作出发点是”便于理解“,并且是面向”设计新手“的。而不少初学者却恰恰觉得这本书难以理解,这说明,作者已经在保证准确性的前提下,选用了他们所认为最便于理解的描述。比本书描述更为显浅的描述,很可能会牺牲准确性(不准确的描述对于新手来说是显然是害处大于好处)。当然某些人认为是作者表达能力有限,这种事情无法求证,但我倾向于前者。
===================================
现在开始正题,如何正确使用设计模式,准确来说,正确使用GoF的《设计模式》一书中所涉及的23种模式。但我们不妨先考虑一个比较容易回答的问题,如何避免不正确地使用设计模式。毕竟不正确地使用还不如不用,你在避免不正确使用的前提下慢慢用起来,就是正确使用了。
使用设计模式最常见走入歧途的做法是:你看了《设计模式》中某个具体模式,觉得似懂非懂,或者甚至根本没看过原书。然后去看了一些举例子打比喻的”再谈“,”妙解“,”大话“之类的东西,觉得豁然开朗。之后在开发时发现某一处非常符合你对这个模式的理解,于是开始使用。这种做法用来练手可以(也就是你明知使用这个模式未必是一个好主意,只是为了尝试在现实场景中去实现一下,练习代码并不进入最终产品代码),用来做真实的设计则往往谬以千里。
原因很简单:设计模式是一种驾驭抽象概念的技术,而描述模式的标准格式里就包括了抽象描述,代码示例和应用场景。如果一个程序员根据这些信息还不能理解一个设计模式的话,说明他首先抽象思维尚不足以驾驭设计模式,其次在理解代码和接触应用场景方面经验不足。简单来说,还未能达到“设计新手”的入门水平。在这种状态下勉强去使用设计模式,出问题是在所难免的。
因而得出第一点:如果你已经看过某个设计模式的描述,要正确使用它的最基本前提是,你能完全看懂GoF《设计模式》中对它的描述。在此之前,只看,不用。看是指看该模式的原文描述或者具体代码。特别地,不建议通过一些类比具体生活例子的方式来理解设计模式。设计模式的写作格式是经过验证,能有效地描述一个模式而又不失准确性的手段。如果你无法理解,看实际生产代码的应用场景是唯一真正有效的方法(因为设计模式本身就是从具体代码中总结出来的)。用类比的方法降低设计模式的抽象性来帮助了解没有实质的意义——即使你觉得自己懂了,你的抽象思维和开发经验还未达到能正确使用这个模式的水平。
正如前面所言,只要你对面向对象一些基本原则有充分的理解,你甚至可能在没看过《设计模式》之前就开始使用某种模式了,如果你已经达到这种程度自然能无压力看懂描述。退一步假如你还没达到这种程度,既然《设计模式》中的模式非常常见,你只要有心多看代码,在现有代码中必然能接触到。通过实际应用的代码与书中的描述互相印证,要理解亦不难。再退一步,假如你接触的代码就一直没遇到 某个模式,你也一直无法自发理解某个模式,那么这个模式就对你没用,你没必要一定要找机会用。
避免不正确使用的第二点是,避免过度设计。这里说的过度设计本质上就是你为可能发生的变动支付了过多的复杂度代价。其实过度设计和设计模式没有必然的关系,只要你认定一个地方会变动,你就会考虑是否应该增加复杂度来换取灵活性。设计模式只不过针对某些具体场景提供了一些效率较高的以复杂度换灵活性的手段而已。避免过度设计的关键是,你能正确评估未雨绸缪所引入的复杂度,相对于发生变动的可能性和破坏力,是否值得。
正确评估变动的可能性和破坏力,只能依靠行业经验,属于资历问题。如果你对当前场景没有足够的经验进行评估,最好的办法就是假定它不会频繁变化,只采用普通的高内聚低耦合策略,而不需要增加额外的复杂度来提供灵活性。等到确认出现变化时,再进行重构。
而对设计模式的认识可能会影响对复杂度的估计,不少设计模式的初学者很容易错误估计实现某个设计模式所带来的复杂度,认为灵活性随手可得。又或者下意识地寻找练手机会而忽略掉复杂性的代价。在假定程序员对某个设计模式已经充分理解的前提下,我觉得评估复杂度时至少应该考虑到这些因素:
1. 需要额外引入哪些新的概念。要明白一段代码涉及的概念越多,就越难理解。
2. 设计模式自身的实现复杂度
3. 一旦引入后,为了保持设计所带来的灵活性,后续开发需要注意的地方。是否能通过代码层面的限制来保证灵活性不会被破坏。
4. 团队中其他人对这个设计模式的理解程度
5. 对排错调试,代码静态分析可能造成的影响 (例如Observer模式和Visitor模式往往会打乱静态分析,难以通过阅读代码确定执行状态)
如果能够大致准确地评估上述要素然后作出决定,我觉得即使变动最终没有发生,也算是一个合格的设计决策。真正的难点在于评估变动,这只能靠经验。还有就是每次做出设计决策后最好能跟踪总结,为下次决策积累经验。
关于设计模式的使用暂时想到这些。
========================
既然题目中提到了“设计模式的荼毒”,这里也说说我认为《设计模式》一书中最大一处问题:一句看上去正确,但被后来一些读物误解并放大,在实际执行中造成最多问题的话:
命名一个新的模式增加了我们的设计词汇。设计模式允许我们在较高的抽象层次上进行设计。基于一个模式词汇表,我们自己以及同事之间就可以讨论模式并在编写文档时使用它们。模式名可以帮助我们思考,便于我们与其他人交流设计思想及设计结果。
这句对“模式名称”要素的描述的话,在很多后续书籍或文章中被引申为:设计模式的一个重要作用是为团队提供了一套方便的交流手段。看上去非常正确,例如,我可以对同事说,这里需要一个Adapter;或者在代码中直接命名XXXApapter,同事们一看就知道这是什么了。交流变得非常方便——前提是,我们都看过《设计模式》并清楚关于这个设计模式的描述。使用设计模式进行交流的结果就是:了解某个设计模式的人跟不了解这个设计模式的人根本无法交流。
而交流在团队中是一种非常基础,不可或缺的东西,进一步的结果就是,了解某个设计模式的人认为不了解这个设计模式的人达不到基础水平。而按照前文的分析,设计模式只不过是对已有开发手段的总结,完全有可能出现某个人的能力已经足够自发使用设计模式,只不过因为没认真看过《设计模式》这本书,而被认为达不到基础水平。这造成了很多有一定编程能力的开发者对设计模式十分反感。
再一步引申的结果是,因为设计模式变成了一种鉴别是否具有基础水平的手段,那么为了让自己看起来有基础以上水平,就必须要表现得懂设计模式——即使看不懂《设计模式》原文。这就给许多“大话”,“再谈”读物带来了市场,进而造就了一大批不是从实际开发或阅读代码中理解设计模式,在实际应用中错漏百出的初学者。链接:https://www.zhihu.com/question/23757906/answer/208892917
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我觉得,设计模式一般应用在模块开发中(比如工具库、中间件等),设计模式就是前人对模块代码设计方式的总结,使得模块代码更加灵活简洁、可维护、可扩展。
试想一下,假设不用任何设计模式,那你会把所有方法放到一个类中吗?显然不会,那么你就要考虑,怎么把不同方法放到不同的类中,这些类怎么协作运行——这个过程就是你自己“创造设计模式”的过程。既然经典设计模式是前人都踩了那么多的坑才总结出来的“精华”,为什么不取其精华而用之呢?
所以,我觉得最好的方法是,首先你要熟悉常用的设计模式,谨记心中;然后在实际开发中套用一些恰当的设计模式,让你写出的代码可维护、易于扩展,而不是写出一坨混乱的代码。
--------------
下面是我对各种设计模式的理解的一句话总结(可以点击设计模式名称进入查看详细内容~)。
希望对你有帮助~
创建型模式
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用新的运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
- 工厂模式与抽象工厂模式 (Factory Pattern)(Abstract Factory Pattern):不同条件下创建不同实例
- 单例模式 (Singleton Pattern):保证一个类仅有一个实例
- 建造者模式 (Builder Pattern):将一个复杂的构建过程与其具表示细节相分离,使得同样的构建过程可以创建不同的表示
- 原型模式 (Prototype Pattern):通过拷贝原型创建新的对象
结构型模式
这些设计模式关注类和对象的组合。
- 适配器模式 (Adapter Pattern):使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
- 装饰器模式 (Decorator Pattern):保持接口,增强性能:修饰类继承被修饰对象的抽象父类,依赖被修饰对象的实例(被修饰对象依赖注入),以实现接口扩展
- 桥接模式 (Bridge Pattern):两个维度独立变化,依赖方式实现抽象与实现分离:需要一个作为桥接的接口/抽象类,多个角度的实现类依赖注入到抽象类,使它们在抽象层建立一个关联关系
- 外观模式 (Facade Pattern):在客户端和复杂系统之间再加一层,这一次将调用顺序、依赖关系等处理好。即封装底层实现,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的高层接口
- 代理模式 (Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问:增加中间层(代理层),代理类与底层实现类实现共同接口,并创建底层实现类对象(底层实现类对象依赖注入代理类),以便向外界提供功能接口
- 过滤器模式 (Filter、Criteria Pattern):使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来
- 组合模式 (Composite Pattern):用户对单个对象和组合对象的使用具有一致性的统一接口
- 享元模式 (Flyweight Pattern):享元工厂类控制;HashMap实现缓冲池重用现有的同类对象,如果未找到匹配的对象,则创建新对象
行为型模式
这些设计模式特别关注对象之间的通信。
- 责任链模式(Chain of Responsibility Pattern):拦截的类都实现统一接口,每个接收者都包含对下一个接收者的引用。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
- 观察者模式(Observer Pattern):一对多的依赖关系,在观察目标类里有一个 ArrayList 存放观察者们。当观察目标对象的状态发生改变,所有依赖于它的观察者都将得到通知,使这些观察者能够自动更新(即使用推送方式)
- 模板模式(Template Pattern):将这些通用算法抽象出来,在一个抽象类中公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行
- 命令模式(Command Pattern):将"行为请求者"与"行为实现者"解耦:调用者依赖命令,命令依赖接收者,调用者Invoker→命令Command→接收者Receiver
- 解释器模式(Interpreter Pattern):给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子
- 迭代器模式(Iterator Pattern):集合中含有迭代器:分离了集合对象的遍历行为,抽象出一个迭代器类来负责,无须暴露该对象的内部表示
- 中介者模式(Mediator Pattern):对象与对象之间存在大量的关联关系,将对象之间的通信关联关系封装到一个中介类中单独处理,从而使其耦合松散,可以独立地改变它们之间的交互
- 策略模式(Strategy Pattern):策略对象依赖注入到context对象,context对象根据它的策略改变而改变它的相关行为(可通过调用内部的策略对象实现相应的具体策略行为)
- 状态模式(State Pattern):状态对象依赖注入到context对象,context对象根据它的状态改变而改变它的相关行为(可通过调用内部的状态对象实现相应的具体行为)
- 备忘录模式(Memento Pattern):通过一个备忘录类专门存储对象状态。客户通过备忘录管理类管理备忘录类。
- 空对象模式(Null Object Pattern):创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方。不要为了屏蔽null而使用空对象,应保持用null,远比用非null的值来替代“无值”要好。(慎用)
链接:https://www.zhihu.com/question/23757906/answer/25567356
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
除非你还在写 Java,否则设计模式真没多大用处。
---- 补充几句 ----
首先明确一点,这里说的“设计模式”,是“面向对象设计模式”的简称,以 GoF 书中列出的 23 个模式为代表。
不要把什么都归为模式,比如 “if-then-else 模式”、“for each 模式”就不是(面向对象设计)模式。Like, the inverse, reverse, double-back-flip pattern—whatever. Oh, you mean a loop? OK. --- Jamie Zawinski
类似的,thread pool、thread-per-connection、process-per-connection、thread local storage、scoped locking、readers-writer lock 等等也不是面向对象设计模式。
赞同
说的 “建议不要泛泛地讨论和学习‘设计模式’,而是具体到每一个模式。”如果你用的语言能把类型像变量一样赋值并传来传去,很多创建型模式就没用了。
如果你用的语言能把函数像变量一样赋值并传来传去,很多行为模式就没用了。
如果你用的语言 style 反对叠床架屋的 class hierarchy,很多结构模式就没用了。
几个简单具体的代码示例:
1. C# 内置了 delegate/event,Observer 模式就没用了。
2. 如果你的语言的 typeof 操作符能得到 runtime type,那么 Prototype 模式就没用了。比如class Base(object):
pass
class Derived(Base):
pass
def clone(x):
return type(x)()
if __name__ == '__main__':
d = Derived()
print type(d) # <class '__main__.Derived'>
c = clone(d)
print type(c) # <class '__main__.Derived'>
b = Base()
print type(b) # <class '__main__.Base'>
a = clone(b)
print type(a) # <class '__main__.Base'>
3. 如果类型能像变量一样赋值和传递,Factory method 模式就没用了。比如
class Base(object):
pass
class Derived(Base):
pass
def getCreator(ty):
def create():
obj = ty()
# initialize obj
return obj
return create
if __name__ == '__main__':
d = getCreator(Derived)
b = getCreator(Base)
print type(d()) # <class '__main__.Derived'>
print type(b()) # <class '__main__.Base'>
# 这个例子做作了一些,可以看第二个链接里的例子。
更多的例子见 http://norvig.com/design-patterns/design-patterns.pdf
http://cdn.oreillystatic.com/en/assets/1/event/12/_The%20Lack%20of_%20Design%20Patterns%20in%20Python%20Presentation.pdf
4. 如果函数能像变量一样赋值和传递,Command、Strategy 等模式就没用了。
5. EventHandler/ConcreteEventHandler 这种 callback API 风格在现代语言里基本绝迹,C++ 有 std::function、C# 有 delegate、连 Java 8 都有了 Lambda,更别说动态语言了。
6. 有的语言有全局变量,Singleton 模式就没用了。Singleton 是最简单也最被滥用的模式。
7. 有的语言有 multiple dispatch,Vistor 模式就没用了。其实 Vistor 模式一直就没啥用。using System.Collections; using System.Collections.Generic; using UnityEngine; public class robotControl2 : MyBehaviour { // Use this for initialization // 设置成单例模式,便于调用 public static robotControl2 _instance; //动画,包括avatar ,state machine. private Animator anim; private Vector3 OffsetV = new Vector3(0, 0, 0); // 角色控制器 private CharacterController controller; private Vector3[] preFrameJoints = new Vector3[25]; // 移动速度 public float speed = 0.3f; private void Awake() { _instance = this; } private void OnEnable() { // float a, b = 0; // Vector3 p1 = new Vector3 (0, 0, 0); // Vector3 p2 = new Vector3 (3, 4, 5); // Vector3 p3 = new Vector3 (1, 0, 0); // Vector3 p4 = new Vector3 (3, 4, 9); // // Vector3 ret = NewP (p1, p2, p3, p4); // // Debug.Log (ret.x); // Debug.Log (ret.y); // Debug.Log (ret.z); StartCoroutine(test()); } private IEnumerator test() { List<List<APPHelper.MyPoint>> records = APPHelper.GetRecords(); foreach (List<APPHelper.MyPoint> listJoints in records) { //update avater motion Vector3[] realVector = new Vector3[25]; for (int i = 0; i < 25; i++) { realVector [i].x = (float)listJoints [i].x; realVector [i].y = (float)listJoints [i].y; realVector [i].z = (float)listJoints [i].z; } UpdataAvaterMotion (realVector); //move avater moveAvatar(listJoints[0]); //MoveRoot(listJoints[0]); //MoveRoot() ////Vector3[] avatarPos = GenerateAvatarJointsPos(listJoints.ToArray()); //avatarPos = GenerateAvatarJointsPos_forAvatarSize(avatarPos); //UpdateAvatar(avatarPos); //Move(listJoints.ToArray()); yield return new WaitForSeconds(0.033333f); } } private void moveAvatar(APPHelper.MyPoint rootPos) { GameObject.Find(APPHelper.gameobject_root).GetComponent<Transform>().position = new Vector3((float)rootPos.x, (float)rootPos.y, (float)rootPos.z); } private void UpdataAvaterMotion(Vector3[] realVector) { //get all avaterJoints Vector3[] AvatarVector=GetAllAvaterJoints(); Vector3 temp1 = NewP (realVector [12], realVector [13], AvatarVector [12], AvatarVector [13]); AvatarVector [13] = temp1; UpdateAvatar (AvatarVector); temp1 = NewP (realVector [13], realVector [14], AvatarVector [13], AvatarVector [14]); AvatarVector [14] = temp1; UpdateAvatar (AvatarVector); temp1 = NewP (realVector [14], realVector [15], AvatarVector [14], AvatarVector [15]); AvatarVector [15] = temp1; UpdateAvatar (AvatarVector); //update motion } public void UpdateAvatar(Vector3[] receiveJoints) { APPHelper.MyJoint[] JointsInfo = APPHelper.InitJoints(); for (int i=0;i< receiveJoints.Length;++i) { if (JointsInfo[i].GBPath!="") { GameObject.Find(JointsInfo[i].GBPath).GetComponent<Transform>().position = new Vector3((float)receiveJoints[i].x, (float)receiveJoints[i].y, (float)receiveJoints[i].z); } } } private Vector3[] GetAllAvaterJoints() { Vector3[] ret = new Vector3[25]; APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); for (int i = 0; i < allJoints.Length; i++) { if (allJoints[i].GBPath != "") { try { ret[i] = GameObject.Find(allJoints[i].GBPath).GetComponent<Transform>().position; } catch (System.Exception _e) { Debug.Log(_e.Message); } } } return ret; } ////// ////private Vector3[] GenerateAvatarJointsPos(APPHelper.MyPoint[] realPos) ////{ //// Vector3[] ret = null; //// if (realPos.Length== 25) //// { //// if (OffsetV.x == 0 && OffsetV.y == 0 && OffsetV.z == 0) //// { //// if (true)//CheckStartInitAvatar. //// { //// //offset=real-avatar //// Vector3 avatarV = GetAvaterRootPosition(); //// OffsetV = new Vector3((float)realPos[0].x - avatarV.x, (float)realPos[0].y - avatarV.y, (float)realPos[0].z - avatarV.z); //// ret = new Vector3[25]; //// for (int i = 0; i < 25; i++) //// { //// ret[i] = new Vector3((float)realPos[i].x - OffsetV.x, (float)realPos[0].y - OffsetV.y, (float)realPos[0].z - OffsetV.z); //// } //// } //// } //// else //// { //// ret = new Vector3[25]; //// for (int i = 0; i < 25; i++) //// { //// ret[i] = new Vector3((float)realPos[i].x - OffsetV.x, (float)realPos[0].y - OffsetV.y, (float)realPos[0].z - OffsetV.z); //// } //// } //// } //// return ret; ////} //// //private Vector3 GetAvaterRootPosition() //{ // return GameObject.Find(APPHelper.gameobject_root).GetComponent<Transform>().position; //} //private void UpdateAvatar(Vector3[] avatarPos) //{ // //MoveRoot(avatarPos[0]); // //GetALL // TestMoveAllJoints(avatarPos); //} //private void MoveRoot(Vector3 rootPos) //{ // GameObject.Find(APPHelper.gameobject_root).GetComponent<Transform>().position = new Vector3(rootPos.x , rootPos.y , rootPos.z); //} //private void MoveRoot(APPHelper.MyPoint rootPos) //{ // GameObject.Find(APPHelper.gameobject_root).GetComponent<Transform>().position = new Vector3((float)rootPos.x, (float)rootPos.y, (float)rootPos.z); //} //private Vector3[] GetJointsAvater() //{ // Vector3[] ret = new Vector3[25]; // APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); // for (int i = 0; i < allJoints.Length; i++) // { // if (allJoints[i].GBPath != "") // { // try // { // ret[i] = GameObject.Find(allJoints[i].GBPath).GetComponent<Transform>().position; // } // catch (System.Exception _e) // { // Debug.Log(_e.Message); // } // } // } // return ret; //} //private Vector3[] GenerateAvatarJointsPos_forAvatarSize(Vector3[] avatarPos) //{ // Vector3[] vv = GetJointsAvater(); // Vector3[] ret = null; // if(avatarPos.Length==25) // { // ret = avatarPos; // ret[0] = avatarPos[0]; // ret[1] = NewP(avatarPos[0], avatarPos[1], vv[0], vv[1]); // } // return ret; //} private Vector3 NewP(Vector3 pp1, Vector3 pp2, Vector3 vp1, Vector3 vp2) { Vector3 ret = new Vector3(); float xyc, zc = 0; GetV(out xyc, out zc, pp1, pp2); ret = GetNewPosition2 (xyc, zc, vp1, vp2, pp1, pp2); return ret; } private void GetV(out float xyMianCos, out float zMianCos, Vector3 p1, Vector3 p2) { Vector3 offsetV = p2 - p1; xyMianCos = offsetV.y / offsetV.x; zMianCos = (float)(offsetV.z / System.Math.Sqrt((offsetV.x * offsetV.x + offsetV.y * offsetV.y))); } private Vector3 GetNewPosition2(float xyMianCos, float zMianCos, Vector3 p1, Vector3 p2,Vector3 pp1,Vector3 pp2 ) { Vector3 offsetV = p2 - p1; Vector3 preOffsetv = pp2 - pp1; float rr = offsetV.x * offsetV.x + offsetV.y * offsetV.y + offsetV.z * offsetV.z; float a = rr / (1 + xyMianCos * xyMianCos); a = (float)(System.Math.Sqrt (a / (1 + zMianCos * zMianCos))); if (preOffsetv.x < 0) { a = -a; } float x = a; float y = xyMianCos * x; float z = (float)(zMianCos * (System.Math.Sqrt (x * x *(1 + xyMianCos * xyMianCos)))); Vector3 ret = new Vector3(x, y, z); ret = ret + p1; return ret; } // private Vector3 GetNewPosition(float xyMianCos, float zMianCos, Vector3 p1, Vector3 p2) // { // Vector3 offsetV = p2 - p1; // // float x = 0; // float y = 0; // GetPosChangeAnger(offsetV.x, offsetV.y, xyMianCos, out x, out y); // // float x1 = 0; // float y1 = 0; // GetPosChangeAnger(offsetV.z, (float)System.Math.Sqrt(offsetV.x * offsetV.x + offsetV.y * offsetV.y), zMianCos, out x1, out y1); // // float z = x1; // // Vector3 ret = new Vector3(x, y, z); // return ret; // // } // // // private void GetPosChangeAnger(float x, float y, float newCos, out float newx, out float newy) // { // newx = 1; // newy = 1; // // float RoundPingfang = x * x + y * y; // newx = RoundPingfang / (1 + newCos * newCos); // newx = (float)System.Math.Sqrt(newx); // // newy = newx * newCos; // } //private void TestMoveAllJoints(Vector3[] avatarPos) //{ // APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); // for(int i=0;i< avatarPos.Length;i++) // { // if(allJoints[i].GBPath!="") // { // try // { // GameObject.Find(allJoints[i].GBPath).GetComponent<Transform>().position = new Vector3(avatarPos[i].x, avatarPos[i].y, avatarPos[i].z); // } // catch (System.Exception _e) // { // Debug.Log(_e.Message); // } // } // } //} ////public void Move(APPHelper.MyPoint[] receiveJoints) ////{ //// APPHelper.MyJoint[] JointsInfo = APPHelper.InitJoints(); //// for (int i=0;i< receiveJoints.Length;++i) //// { //// if (JointsInfo[i].GBPath!="") //// { //// GameObject.Find(JointsInfo[i].GBPath).GetComponent<Transform>().position = new Vector3((float)receiveJoints[i].x, (float)receiveJoints[i].y, (float)receiveJoints[i].z); //// } //// } ////} ////private void Start() ////{ //// anim = this.GetComponent<Animator>(); //// controller = this.GetComponent<CharacterController>(); //// APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); //// int index = 0; //// foreach (APPHelper.MyJoint joint in allJoints) //// { //// if (joint.GBPath != "") //// { //// preFrameJoints[index] = GameObject.Find(joint.GBPath).GetComponent<Transform>().position; //// index++; //// } //// } //// StartCoroutine(CheckJoint()); ////} ////private void Update() ////{ ////} ////private IEnumerator CheckJoint() ////{ //// APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); //// Vector3[] newPosition = new Vector3[25]; //// int index = 0; //// foreach (APPHelper.MyJoint joint in allJoints) //// { //// if (joint.GBPath!="") //// { //// try //// { //// Debug.Log(joint.GBPath); //// //Vector3 tempVector = GameObject.Find(joint.GBPath).GetComponent<Transform>().position; //// GameObject.Find(joint.GBPath).GetComponent<Transform>().position = new Vector3(preFrameJoints[index].x, preFrameJoints[index].y, preFrameJoints[index].z+1); //// preFrameJoints[index] = GameObject.Find(joint.GBPath).GetComponent<Transform>().position; //// index++; //// } //// catch(System.Exception _e) //// { //// Debug.Log(_e.Message); //// } //// } //// yield return new WaitForSeconds(1); //// } ////} }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class robotControl2 : MyBehaviour { // Use this for initialization // 设置成单例模式,便于调用 public static robotControl2 _instance; //动画,包括avatar ,state machine. private Animator anim; private Vector3 OffsetV = new Vector3(0, 0, 0); // 角色控制器 private CharacterController controller; private Vector3[] preFrameJoints = new Vector3[25]; // 移动速度 public float speed = 0.3f; private void Awake() { _instance = this; } private void OnEnable() { // float a, b = 0; // Vector3 p1 = new Vector3 (0, 0, 0); // Vector3 p2 = new Vector3 (3, 4, 5); // Vector3 p3 = new Vector3 (1, 0, 0); // Vector3 p4 = new Vector3 (3, 4, 9); // // Vector3 ret = NewP (p1, p2, p3, p4); // // Debug.Log (ret.x); // Debug.Log (ret.y); // Debug.Log (ret.z); StartCoroutine(test()); } private void checkOffset(Vector3 realRoot,Vector3 avaRoot) { if (OffsetV.x == 0 && OffsetV.y == 0 && OffsetV.z == 0) { if (true) { OffsetV=realRoot - avaRoot; } } } public void updataAvater1(Vector3[] realVector) { checkOffset (realVector [0], GameObject.Find (APPHelper.gameobject_root).GetComponent<Transform> ().position); UpdataAvaterMotion (realVector); //move avater MoveRoot(realVector [0]-OffsetV); } private IEnumerator test() { List<List<APPHelper.MyPoint>> records = APPHelper.GetRecords(); foreach (List<APPHelper.MyPoint> listJoints in records) { //update avater motion Vector3[] realVector = new Vector3[25]; for (int i = 0; i < 25; i++) { realVector [i].x = (float)listJoints [i].x; realVector [i].y = (float)listJoints [i].y; realVector [i].z = (float)listJoints [i].z; } UpdataAvaterMotion (realVector); //move avater APPHelper.MyPoint movePoint=new APPHelper.MyPoint(); movePoint.x = (float)listJoints [0].x; movePoint.y = (float)(listJoints [0].y+1); movePoint.z = (float)listJoints [0].z; moveAvatar(movePoint); //MoveRoot(listJoints[0]); //MoveRoot() ////Vector3[] avatarPos = GenerateAvatarJointsPos(listJoints.ToArray()); //avatarPos = GenerateAvatarJointsPos_forAvatarSize(avatarPos); //UpdateAvatar(avatarPos); //Move(listJoints.ToArray()); yield return new WaitForSeconds(0.033333f); } } private void moveAvatar(APPHelper.MyPoint rootPos) { GameObject.Find(APPHelper.gameobject_root).GetComponent<Transform>().position = new Vector3((float)rootPos.x, (float)rootPos.y, (float)rootPos.z); } private void UpdataAvaterMotion(Vector3[] realVector) { //get all avaterJoints Vector3[] AvatarVector=GetAllAvaterJoints(); APPHelper.MyJoint[] JointsInfo = APPHelper.InitJoints(); RotationParentP (2, 1, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); //RotationParentP (4, 1, AvatarVector, realVector, JointsInfo); //AvatarVector=GetAllAvaterJoints(); //RotationParentP (8, 1, AvatarVector, realVector, JointsInfo); //AvatarVector=GetAllAvaterJoints(); RotationParentP (5, 4, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (6, 5, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (5, 4, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (6, 5, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (9, 8, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (10, 9, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (13, 12, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (14, 13, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (15, 14, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (17, 16, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (18, 17, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); RotationParentP (19, 18, AvatarVector, realVector, JointsInfo); AvatarVector=GetAllAvaterJoints(); //update motion } private void RotationParentP(int childindex,int paIndex,Vector3[] AvatarVector,Vector3[] realVector,APPHelper.MyJoint[] alljoint) { Vector3 AvatarV = AvatarVector [childindex] - AvatarVector [paIndex]; Vector3 realV = realVector [childindex] - realVector [paIndex]; GameObject.Find (alljoint[paIndex].GBPath).transform.rotation = OneLine (realV, AvatarV,GameObject.Find (alljoint[paIndex].GBPath).transform.rotation); } private Quaternion OneLine(Vector3 descPoint, Vector3 sourcePoint,Quaternion qq) { Quaternion q = new Quaternion (); q.SetFromToRotation(sourcePoint, descPoint); return q * qq ; } public void UpdateAvatar(Vector3[] receiveJoints) { APPHelper.MyJoint[] JointsInfo = APPHelper.InitJoints(); for (int i=0;i< receiveJoints.Length;++i) { if (JointsInfo[i].GBPath!="") { GameObject.Find(JointsInfo[i].GBPath).GetComponent<Transform>().position = new Vector3((float)receiveJoints[i].x, (float)receiveJoints[i].y, (float)receiveJoints[i].z); } } } private Vector3[] GetAllAvaterJoints() { Vector3[] ret = new Vector3[25]; APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); for (int i = 0; i < allJoints.Length; i++) { if (allJoints[i].GBPath != "") { try { ret[i] = GameObject.Find(allJoints[i].GBPath).GetComponent<Transform>().position; } catch (System.Exception _e) { Debug.Log(_e.Message); } } } return ret; } // // // private Vector3[] GenerateAvatarJointsPos(APPHelper.MyPoint[] realPos) // { // Vector3[] ret = null; // if (realPos.Length== 25) // { // if (OffsetV.x == 0 && OffsetV.y == 0 && OffsetV.z == 0) // { // if (true)//CheckStartInitAvatar. // { // //offset=real-avatar // Vector3 avatarV = GetAvaterRootPosition(); // OffsetV = new Vector3((float)realPos[0].x - avatarV.x, (float)realPos[0].y - avatarV.y, (float)realPos[0].z - avatarV.z); // // ret = new Vector3[25]; // for (int i = 0; i < 25; i++) // { // ret[i] = new Vector3((float)realPos[i].x - OffsetV.x, (float)realPos[0].y - OffsetV.y, (float)realPos[0].z - OffsetV.z); // } // } // } // else // { // ret = new Vector3[25]; // for (int i = 0; i < 25; i++) // { // ret[i] = new Vector3((float)realPos[i].x - OffsetV.x, (float)realPos[0].y - OffsetV.y, (float)realPos[0].z - OffsetV.z); // } // } // } // return ret; // } //// //private Vector3 GetAvaterRootPosition() //{ // return GameObject.Find(APPHelper.gameobject_root).GetComponent<Transform>().position; //} //private void UpdateAvatar(Vector3[] avatarPos) //{ // //MoveRoot(avatarPos[0]); // //GetALL // TestMoveAllJoints(avatarPos); //} private void MoveRoot(Vector3 rootPos) { GameObject.Find(APPHelper.gameobject_root).GetComponent<Transform>().position = new Vector3(rootPos.x , rootPos.y , rootPos.z); } //private void MoveRoot(APPHelper.MyPoint rootPos) //{ // GameObject.Find(APPHelper.gameobject_root).GetComponent<Transform>().position = new Vector3((float)rootPos.x, (float)rootPos.y, (float)rootPos.z); //} //private Vector3[] GetJointsAvater() //{ // Vector3[] ret = new Vector3[25]; // APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); // for (int i = 0; i < allJoints.Length; i++) // { // if (allJoints[i].GBPath != "") // { // try // { // ret[i] = GameObject.Find(allJoints[i].GBPath).GetComponent<Transform>().position; // } // catch (System.Exception _e) // { // Debug.Log(_e.Message); // } // } // } // return ret; //} //private Vector3[] GenerateAvatarJointsPos_forAvatarSize(Vector3[] avatarPos) //{ // Vector3[] vv = GetJointsAvater(); // Vector3[] ret = null; // if(avatarPos.Length==25) // { // ret = avatarPos; // ret[0] = avatarPos[0]; // ret[1] = NewP(avatarPos[0], avatarPos[1], vv[0], vv[1]); // } // return ret; //} private Vector3 NewP(Vector3 pp1, Vector3 pp2, Vector3 vp1, Vector3 vp2) { Vector3 ret = new Vector3(); float xyc, zc = 0; GetV(out xyc, out zc, pp1, pp2); ret = GetNewPosition2 (xyc, zc, vp1, vp2, pp1, pp2); return ret; } private void GetV(out float xyMianCos, out float zMianCos, Vector3 p1, Vector3 p2) { Vector3 offsetV = p2 - p1; xyMianCos = offsetV.y / offsetV.x; zMianCos = (float)(offsetV.z / System.Math.Sqrt((offsetV.x * offsetV.x + offsetV.y * offsetV.y))); } private Vector3 GetNewPosition2(float xyMianCos, float zMianCos, Vector3 p1, Vector3 p2,Vector3 pp1,Vector3 pp2 ) { Vector3 offsetV = p2 - p1; Vector3 preOffsetv = pp2 - pp1; float rr = offsetV.x * offsetV.x + offsetV.y * offsetV.y + offsetV.z * offsetV.z; float a = rr / (1 + xyMianCos * xyMianCos); a = (float)(System.Math.Sqrt (a / (1 + zMianCos * zMianCos))); if (preOffsetv.x < 0) { a = -a; } float x = a; float y = xyMianCos * x; float z = (float)(zMianCos * (System.Math.Sqrt (x * x *(1 + xyMianCos * xyMianCos)))); Vector3 ret = new Vector3(x, y, z); ret = ret + p1; return ret; } // private Vector3 GetNewPosition(float xyMianCos, float zMianCos, Vector3 p1, Vector3 p2) // { // Vector3 offsetV = p2 - p1; // // float x = 0; // float y = 0; // GetPosChangeAnger(offsetV.x, offsetV.y, xyMianCos, out x, out y); // // float x1 = 0; // float y1 = 0; // GetPosChangeAnger(offsetV.z, (float)System.Math.Sqrt(offsetV.x * offsetV.x + offsetV.y * offsetV.y), zMianCos, out x1, out y1); // // float z = x1; // // Vector3 ret = new Vector3(x, y, z); // return ret; // // } // // // private void GetPosChangeAnger(float x, float y, float newCos, out float newx, out float newy) // { // newx = 1; // newy = 1; // // float RoundPingfang = x * x + y * y; // newx = RoundPingfang / (1 + newCos * newCos); // newx = (float)System.Math.Sqrt(newx); // // newy = newx * newCos; // } //private void TestMoveAllJoints(Vector3[] avatarPos) //{ // APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); // for(int i=0;i< avatarPos.Length;i++) // { // if(allJoints[i].GBPath!="") // { // try // { // GameObject.Find(allJoints[i].GBPath).GetComponent<Transform>().position = new Vector3(avatarPos[i].x, avatarPos[i].y, avatarPos[i].z); // } // catch (System.Exception _e) // { // Debug.Log(_e.Message); // } // } // } //} ////public void Move(APPHelper.MyPoint[] receiveJoints) ////{ //// APPHelper.MyJoint[] JointsInfo = APPHelper.InitJoints(); //// for (int i=0;i< receiveJoints.Length;++i) //// { //// if (JointsInfo[i].GBPath!="") //// { //// GameObject.Find(JointsInfo[i].GBPath).GetComponent<Transform>().position = new Vector3((float)receiveJoints[i].x, (float)receiveJoints[i].y, (float)receiveJoints[i].z); //// } //// } ////} ////private void Start() ////{ //// anim = this.GetComponent<Animator>(); //// controller = this.GetComponent<CharacterController>(); //// APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); //// int index = 0; //// foreach (APPHelper.MyJoint joint in allJoints) //// { //// if (joint.GBPath != "") //// { //// preFrameJoints[index] = GameObject.Find(joint.GBPath).GetComponent<Transform>().position; //// index++; //// } //// } //// StartCoroutine(CheckJoint()); ////} ////private void Update() ////{ ////} ////private IEnumerator CheckJoint() ////{ //// APPHelper.MyJoint[] allJoints = APPHelper.InitJoints(); //// Vector3[] newPosition = new Vector3[25]; //// int index = 0; //// foreach (APPHelper.MyJoint joint in allJoints) //// { //// if (joint.GBPath!="") //// { //// try //// { //// Debug.Log(joint.GBPath); //// //Vector3 tempVector = GameObject.Find(joint.GBPath).GetComponent<Transform>().position; //// GameObject.Find(joint.GBPath).GetComponent<Transform>().position = new Vector3(preFrameJoints[index].x, preFrameJoints[index].y, preFrameJoints[index].z+1); //// preFrameJoints[index] = GameObject.Find(joint.GBPath).GetComponent<Transform>().position; //// index++; //// } //// catch(System.Exception _e) //// { //// Debug.Log(_e.Message); //// } //// } //// yield return new WaitForSeconds(1); //// } ////} }
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; using System.IO; //范围局限在这个程序中的 可复用代码和全局定义 public class APPHelper { //资源定义 public static string globalsorce_bullet_profebs_path = "Profebs/profebs_bullet"; public static string globalsource_stone = "Profebs/Stone"; //游戏对象定义 public static string globalgameobject_bulltePosition = "player/bulltePosition"; public static string globalgameobject_box = "Box"; public static string gameobject_canvas = "Canvas"; public static string gameobject_socoreLabel = "Canvas/Text"; public static string gameobject_btn_restart = "Canvas/Restart"; public static string gameobject_palyer = "player"; public static string gameobject_ball = "Ball"; public static string gameobject_camera = "Main Camera"; public static string gameobject_root = "Robot/Root"; //游戏tag定义 public static string global_stone_tag = "stone"; public static string global_bullet_tag = "bullet"; public static string global_palyer_tag = "player"; public static string global_pin_tag = "tag_pin"; //全局变量定义 public static float bulletSpeed = 3; public static float playerSpeed = 3; public static int stone_minx = -5; public static int stone_maxx = 5; public static int stone_y = 1; public static int stone_z = 8; public static int stone_speed = 3; public static bool newRoad = true; public static bool audioPlay = false; public static List<List<GAMEMSG.Joint>> alljoints = new List<List<GAMEMSG.Joint>>(); public static List<MyPoint> records = new List<MyPoint>(); public struct MyJoint { public string SensorJoint { get; set; } public int SensorInt { get; set; } public string GBPath { get; set; } } public static MyJoint[] InitJoints() { MyJoint[] ret = new MyJoint[25]; ret[0].SensorJoint = ""; ret[0].SensorInt = 0; ret[0].GBPath = "Robot/Root"; ret[1].SensorJoint = ""; ret[1].SensorInt = 1; ret[1].GBPath = "Robot/Root/Ribs"; ret[2].SensorJoint = ""; ret[2].SensorInt = 2; ret[2].GBPath = "Robot/Root/Ribs/Neck"; ret[3].SensorJoint = ""; ret[3].SensorInt =3; ret[3].GBPath = "Robot/Root/Ribs/Neck/Head"; ret[4].SensorJoint = ""; ret[4].SensorInt = 4; ret[4].GBPath = "Robot/Root/Ribs/Left_Shoulder_Joint_01"; ret[5].SensorJoint = ""; ret[5].SensorInt = 5; ret[5].GBPath = "Robot/Root/Ribs/Left_Shoulder_Joint_01/Left_Upper_Arm_Joint_01/Left_Forearm_Joint_01"; ret[6].SensorJoint = ""; ret[6].SensorInt = 6; ret[6].GBPath = "Robot/Root/Ribs/Left_Shoulder_Joint_01/Left_Upper_Arm_Joint_01/Left_Forearm_Joint_01/Left_Wrist_Joint_01"; ret[7].SensorJoint = ""; ret[7].SensorInt = 7; ret[7].GBPath = ""; ret[8].SensorJoint = ""; ret[8].SensorInt = 8; ret[8].GBPath = "Robot/Root/Ribs/Right_Shoulder_Joint_01"; ret[9].SensorJoint = ""; ret[9].SensorInt = 9; ret[9].GBPath = "Robot/Root/Ribs/Right_Shoulder_Joint_01/Right_Upper_Arm_Joint_01/Right_Forearm_Joint_01"; ret[10].SensorJoint = ""; ret[10].SensorInt = 10; ret[10].GBPath = "Robot/Root/Ribs/Right_Shoulder_Joint_01/Right_Upper_Arm_Joint_01/Right_Forearm_Joint_01/Right_Wrist_Joint_01"; ret[11].SensorJoint = ""; ret[11].SensorInt = 11; ret[11].GBPath = ""; ret[12].SensorJoint = ""; ret[12].SensorInt = 12; ret[12].GBPath = "Robot/Root/Hip/Left_Thigh_Joint_01"; ret[13].SensorJoint = ""; ret[13].SensorInt = 13; ret[13].GBPath = "Robot/Root/Hip/Left_Thigh_Joint_01/Left_Knee_Joint_01"; ret[14].SensorJoint = ""; ret[14].SensorInt = 14; ret[14].GBPath = "Robot/Root/Hip/Left_Thigh_Joint_01/Left_Knee_Joint_01/Left_Ankle_Joint_01"; ret[15].SensorJoint = ""; ret[15].SensorInt = 15; ret[15].GBPath = "Robot/Root/Hip/Left_Thigh_Joint_01/Left_Knee_Joint_01/Left_Ankle_Joint_01/Left_Toe_Joint_01"; ret[16].SensorJoint = ""; ret[16].SensorInt = 16; ret[16].GBPath = "Robot/Root/Hip/Right_Thigh_Joint_01"; ret[17].SensorJoint = ""; ret[17].SensorInt = 17; ret[17].GBPath = "Robot/Root/Hip/Right_Thigh_Joint_01/Right_Knee_Joint_01"; ret[18].SensorJoint = ""; ret[18].SensorInt = 18; ret[18].GBPath = "Robot/Root/Hip/Right_Thigh_Joint_01/Right_Knee_Joint_01/Right_Ankle_Joint_01"; ret[19].SensorJoint = ""; ret[19].SensorInt = 19; ret[19].GBPath = "Robot/Root/Hip/Right_Thigh_Joint_01/Right_Knee_Joint_01/Right_Ankle_Joint_01/Right_Toe_Joint_01"; ret[20].SensorJoint = ""; ret[20].SensorInt = 20; ret[20].GBPath = ""; ret[21].SensorJoint = ""; ret[21].SensorInt = 21; ret[21].GBPath = ""; ret[22].SensorJoint = ""; ret[22].SensorInt = 22; ret[22].GBPath = ""; ret[23].SensorJoint = ""; ret[23].SensorInt =23; ret[23].GBPath = ""; ret[24].SensorJoint = ""; ret[24].SensorInt = 24; ret[24].GBPath = ""; return ret; } public abstract class MessageType { public static byte main_appData = 0x01; public static byte main_appSystem = 0x02; public static byte sub_body = 0x01; public static byte sub_color = 0x02; public static byte sub_hand = 0x03; } //处理消息 public static void OnProcessMsg(List<Message> msgs) { if(GlobalDefine.isNeedNetwork==false) { return; } foreach (Message msg in msgs) { //Debug.Log("msg cmd:" + msg.mainCmd + "." + msg.subCmd + "."); try { if (msg.mainCmd == MessageType.main_appData) { if (msg.subCmd == MessageType.sub_color) { GAMEMSG.DataColor dc = GAMEMSG.DataColor.ParseFrom(msg.msgBody); //Debug.Log("color IMGData:" + dc.IMGData.ToStringUtf8()); } else if (msg.subCmd == MessageType.sub_body) { GAMEMSG.DataBody dc = GAMEMSG.DataBody.ParseFrom(msg.msgBody); List<GAMEMSG.Joint> joints = dc.BodyJointList.ToList(); Vector3[] tempPoint=new Vector3[25]; try { if(joints.Count==25) { for(int i=0;i<25;i++) { tempPoint[i].x=(float)joints[i].JointPoint.X; tempPoint[i].y=(float)joints[i].JointPoint.Y; tempPoint[i].x=(float)joints[i].JointPoint.Z; } } robotControl2._instance.updataAvater1(tempPoint); } catch { } } } else { } } catch (Exception _e) { Debug.Log("except:" + _e.Message); } } } public struct MyPoint { public int id { get; set; } public double x { get; set; } public double y { get; set; } public double z { get; set; } } public static List<List<MyPoint>> GetRecords() { List<List<MyPoint>> ret = new List<List<MyPoint>>(); System.IO.FileStream fs = new FileStream("records54.txt", FileMode.Open); StreamReader mysr = new StreamReader(fs); int readed = 0; List<MyPoint> tempList = new List<MyPoint>(); while (!mysr.EndOfStream) { string tempLine = mysr.ReadLine(); readed++; MyPoint tempPoint = new MyPoint(); string[] splitRet= tempLine.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); tempPoint.id = int.Parse(splitRet[0]); tempPoint.x = float.Parse(splitRet[1]); tempPoint.y = float.Parse(splitRet[2]); tempPoint.z = -float.Parse(splitRet[3]); tempList.Add(tempPoint); //tempList.Add(new ) get joint .and add to tempList if (readed==25) { ret.Add(tempList); tempList = new List<MyPoint>(); readed = 0; } } return ret; } }