关于学习脚本的一些方法和心得

最近有朋友想学习 Max 和 Maya 的脚本编写,但不知道以怎样的方式来有效进行,来信问我有没有什么建议,借此机会我也想专门写一下我自己关于脚本学习的一些经验心得,分享给有所有有需要的朋友。

首先,3D 软件的脚本语言主要分两大类:

一是国内用户接触比较多的 MaxScript 脚本,顾名思义只能在 3DMax 里使用,由于 Max 是国内游戏动画行业最普遍的软件(没有之一),所以学会 MaxScript 脚本对于在国内从事游戏开发工作的动画师来说会比较有用。

二是 Python,一种更加通用普及的脚本语言,除了 Max 以外的其他所有 3D 软件几乎都支持 Python 脚本(新版本的 Max 也开始支持 Python,但并不成熟)。像 Maya,MotionBuilder,Blender,Cinema4D,甚至是 Unreal4 引擎等等,全都以 Python 作为主要脚本语言。也就是说如果学会了基本的 Python 语法,即可以在不同软件里编写需要的脚本工具而不必重新学习新语法。

所以,对于选择什么样的语言,我的看法是,如果明确自己主要学习内容是 Max 方向,那 MaxScript 自然是首选,而如果想一通百通,则 Python 可以带你自由翱翔。

其次,工欲善其事,必先利其器:

选择合适自己的脚本编写工具,对提高效率非常有帮助。写脚本其实就是打字,理论上用 windows 自带的记事本也能做,但就像理论上用 windows 的画笔也能做 photoshop 的效果,但在效率上却是天壤之别一样,我们通常会选用更加适合编程开发的文本编辑工具,我自己主要是用 sublime 3(官网下载链接

sublime 的主要优点在于:

  • 轻量,无需安装复杂的编程环境,使用起来像记事本一样简单
  • 语法高亮,通过不同演示来区分关键字,方便阅读。默认支持 Python 高亮,也可以额外添加 maxscript 高亮配置
  • 强大的检索,文本批量选择,批量修改,统一行首格式 等功能

虽然 sublime 相对于更加专业的编程用文本编辑器来说,缺少一些更复杂的功能,但对于写脚本是足够用了。

有了 sublime 后,还需要一个科学上网环境,使你能方便的访问 Google,随时检索自己不明白的命令或功能,但这个就要靠读者自己来解决了,如果公司有比较好的上网环境那最好,如果是个人在家的话,一般使用 VPN,但一切请遵守当地法律法规

另外有条件的话最好有 2 个显示器,一个显示 3D 软件,用于查看执行结果,另一个显示自己的代码和文档网页,方便提高工作效率。

(lll¬ω¬)

冗长的铺垫完后,开始讲主题,怎么学习写脚本:

首先声明一点,我自己没有通过任何实体书籍来学习脚本编程,所以无法做相关的推荐,但从我自己的经验来看,其实完全不必靠书来完成学习,一切以需求驱动

什么是需求?什么时候会有对脚本的需求?那就要回答一个问题,那就是脚本到底能做什么?

脚本说白了就是个批量处理工具,用它来自动化的,重复的,快速的执行原本需要用户手动操作的程序功能

比如我要在 Max 里创建 1 个 圆球,手动操作就是在菜单面板里找到 sphere 按钮,点击它,然后通过在 3D 视图里拖拽鼠标,来设定好球的大小和位置,完成。很简单对不对?那如果我需要创建 1000 个大小不同,并以一定规律排列的圆球呢?我当然也可以逐一手动添加,花几个小时乃至一整天来做,但我肯定会觉得枯燥觉得浪费时间。而每当你觉得你在做枯燥和浪费时间的工作的时候,就是你对脚本有需求的时候。

再比如我之前做的 SpringMax 飘带工具,其实所做的也只是在动画的每一帧,将骨骼链的每一根骨骼,以一种固定的模式来偏转,最后整体播放的时候就能产生跟随飘动甚至碰撞的效果,如果让我手动来做飘带,肯定也能花时间完成同样的效果,只是我会觉得枯燥并且浪费时间罢了。

而对于一些你不知道该怎么才能做到的效果,那即使你会写脚本也无济于事,因为它只能做你知道操作步骤的工作,并不能实现你所不知道的事情,对计算机来说没有魔法。

那明白了脚本的这个工具的定位,我们接下来就可以去 B 站搜一下 maxscript 或者 python 这样的关键字,看一些最最基本入门语法和编写简单功能的视频教程,最多花个一下午,你就至少对于你所用的软件在哪里输入脚本,语法格式,怎么执行,怎么看报错提示,怎么排查问题等等,有了个初步的概念,因为相关教程已经很多了,我就不说这些车轱辘话了。

接下来,再回到那 1000 个球的问题,作为一个初学者,我打算解决这个问题,我在 sublime 里郑重的输入我自己的第一行代码,这是我忽然发现我不知道怎么创建哪怕一个球体,这该怎么办?不用怕,打开 google 搜索引号里的关键字 “maxscript sphere”

通常, autodesk 官方的帮助文档就会显示在头几个,点开以后就可以查看 官方帮助文档关于 sphere 的解释,官方帮助文档,作用类似于字典,对于脚本的命令功能具有最详细和最权威的解释,想来也能明白,因为都是他们开发的嘛。这里也希望读者能培养良好的,优先查阅官方说明的习惯,虽然是英文的,但熟悉以后来来去去就那么几个词,不会太费力气,最主要的是可以省去将来因为一知半解而走弯路所浪费的精力。

另外对于一些更复杂的问题,比如如何得知骨骼的旋转数值?也可以直接 google 搜索 “maxscript bone rotation” 这样的关键词

因为作为初学者所接触到的问题,几乎都已经有人问过,讨论过,并且有现成的答案和解决方法,你所要做的只是把他们找出来而已。也许读者要问,为什么不用 baidu 搜?因为很遗憾,baidu 往往找不到这方面有用的信息,而且中文互联网的相关讨论也远不如英文资源丰富,所以学好英语会很有帮助哦,而且专业术语的英文词汇多熟悉也是应该的,再说了实在看不懂也可以用 google 翻译嘛。

另外多说一句,对于 Maya 的Python 编写,建议使用 Pymel ,它的功能完备且官方文档包含很多使用示例,非常有帮助,我的 Maya 工具都是 Pymel 写的。

再一个就是查阅范例脚本,Maya 和 Motion Builder 在这方面做的比较好,随软件附带了范例脚本( 在软件安装目录搜 “*.py” 文件,然后找到位于 sample 字样文件夹里的,就是它们了 ),列出了许多基本功能的编写方法,你甚至可以直接找到相关的语句,复制黏贴到自己的代码里就行。Max 并没有随软件附带范例,需要批评,不过好在有大把工具网站,人们在上面分享了自己的脚本,找自己感兴趣的下载后,拖到 sublime 里就能查看,在配合搜索功能来查找别人脚本里自己想了解的内容。

我写脚本的工作流程:

  1. 明确目标,知道最终所要解决的具体问题是什么,并且先 Google 搜一下是否已经存在别人写的类似功能的脚本可以直接下载使用,免去重复劳动
  2. 明确步骤,可以画个草图,把最终问题拆分成一个个小步骤,然后每个小步骤之间的先后关系理顺
  3. 就像写文章一样,每一个小步骤写一段代码专门处理,遇到不懂的地方就 google 搜关键字,查阅官方文档,看看别人的对于相关具体问题的讨论,基本都能找到答案,每完成一个小步骤就在软件里执行一次,看看返回的结果是否正确,以免错误累加
  4. 逐个完成所有的步骤后,看总体执行结果,如果结果不正确,则需要分析是设计思路问题还是编写时候疏漏造成的错误,再根据错误提示来修改调整

不知不觉写了这么多了,再有想说的就是,学无止境,一开始切忌贪多求全,从自己的具体需求出发,一点一点来,一次解决一个具体的小问题,逐渐积累并加深认识。而这也是为什么我不看书学的原因,因为书里也许知识很丰富,讲解很生动,代码结构很合理,但唯独没有能解决我当前实际需求的东西,这很容易令我失去耐心,难以保持学习的热情。

不要担心自己写的语法是否标准,结构是否合理,运行是否高效,作为非专业的编程爱好者,写出来的工具能正确运行,能实现自己的需求就是王道,完全可以忽略这些细枝末节的问题,埋头写自己的代码就是了。

兴趣才是最好的老师!

最后,欢迎各位留言,说说自己对这个问题的看法,或者哪些内容需要补充,我再详细展开说。

希望能帮到有需要的人

谢谢

 

《关于学习脚本的一些方法和心得》有15个想法

  1. 你好,我在看了你帖子后准备开始使用Sublime学习MaxScript,它真的很好用。但有一个问题:我没法是sublime和max关联起来,只有当保存ms文件后才能正确的在max中运行。请问知道怎么解决这个问题吗?没有办法在网上对应的解决办法。

    1. 你好,关于这部分我确实漏掉了,网上找了个现成的英文教程,链接如下:
      http://www.designimage.co.uk/sublime-text-3dsmax-python/

      主要就是配置一个 sublime 的 maxscript 插件

      另外我个人用的方法更偷懒一些,是在 max 工具栏里直接加一个正在编写的脚本的按钮,在每次修改脚本后点一下那个按钮来执行,方法是先把下面这个命令写在 listener 里,然后全选这段文字,鼠标左键拖拽到 3D 视图上方的工具栏,再改个自己喜欢的名字或图标
      fileIn(@”你的脚本完整路径”)

  2. 白老师您好,我最近在学习MoBu的Python脚本编写,遇到一个问题想要请教一下。我想实现在选中一根骨骼的时候,拉取被选中骨骼的空间名,并引用它,比如:
    rh = FBFindModelByLabelName( ‘Xxx:Hips’)
    rh.Selected = True
    rh.Selected = False
    rh.Rotation = FBVector3d(90,0,0)
    我想要用当前选中骨骼的空间名来替换这个Xxx,代码应该怎么写呢。

    1. 你好,首先我不是很确定你所说的“空间名”具体含义是指什么,其次 ‘Xxx:Hips’ 应该是一个 rigging 的 hips 控制器名字对吧?其中的 Xxx 是这个 character 的名称,如果要改,就需要该整个 character 的名称,而不能单单在这一个控制器上改而其他的不变

      1. 首先感谢大佬的回复。举个例子,就是在MoBu里面有A/B两套带NameSpace的角色骨骼,我需要分别给这两套骨骼调整到标准的T-Pose来进行重定向。我写了一段代码来调整每根骨骼的旋转值,就是这一段(A指的是它的NameSpace,Hips是它其中的一根骨骼)
        rh = FBFindModelByLabelName( ‘A:Hips’)
        rh.Selected = True
        rh.Selected = False
        rh.Rotation = FBVector3d(90,0,0)
        但是我如果要调整B角色的话,就需要再写一段同样的代码
        rh = FBFindModelByLabelName( ‘B:Hips’)
        rh.Selected = True
        rh.Selected = False
        rh.Rotation = FBVector3d(90,0,0)
        这样就很繁琐,因为每个项目的角色骨骼的空间名都是不一样的,每次都需要再单独写代码。所以我在想是不是有一段代码可以直接拉取当前场景中选中的骨骼的NameSpace来直接替代这个A/B,这样可以省去很多时间。
        不知道这样描述,大佬是否能够明白我的意思。再次感谢大佬花时间来回复我这个小白的问题~~

          1. 又来求助大佬了(捂脸)。
            获取当前选中物体的空间名代码我在论坛搞到了,执行这段代码(选中物体的空间名是zhenchipeng)
            from pyfbsdk import *

            def GetSelModelNameSpace():
            lSelModels = []
            modelList = FBModelList()
            FBGetSelectedModels (modelList, None, True)
            for model in modelList:
            if model.Selected == True:
            lSelModels.extend( [ model.LongName.rsplit(‘:’, 1)[0] ] )
            return lSelModels[0]

            myNameSpace = GetSelModelNameSpace()
            print (myNameSpace + ‘:Hips’)
            得到结果 zhenchipeng:Hips
            但是我在继续执行下面一段代码的时候并没有什么效果
            rh = FBFindModelByLabelName( myNameSpace + ‘:Hips’ )
            rh.Selected = True
            rh.Rotation = FBVector3d(90,0,0) #Lcl
            不知道哪里出了问题,是myNameSpace + ‘:Hips’ 这里的语法么?希望可以得到大佬的解答。

            1. rh = FBFindModelByLabelName( myNameSpace + ‘:Hips’ )
              这之后 print 一下 rh.Name 看是不是真的 get 到了,另外 FBFindModelByLabelName 返回的是个 List,你需要取的应该是其中第一个,所以语句需要改成
              rh = FBFindModelByLabelName( myNameSpace + ‘:Hips’ )[0]
              但还是要 print 来确认得到你要的东西

              1. 大佬,我又来了~上次的一键T-Pose脚本已经搞定了。感谢大佬的分享~~最近想要实现一个新的功能。
                是这样的,已经T-Pose好的骨骼,从Browser里拖拽character给它角色化的话,量大起来就有些繁琐。我想既然已经可以一键T-Pose了,那么为什么不把角色化的功能也写一个按钮呢,然而苦于不知道这段代码应该怎么写。咳咳,查阅了很多案例,还是搞不定,想过来咨询一下大佬有没有什么解决思路~

发表评论

邮箱地址不会被公开。 必填项已用*标注