cnu2018-RobotSim

嘉藥-互動科技-Unity-RobotSim

卓智創意互動科技

Unity應用案例(廣告時間)

工具們

  1. Unity wiki
  2. Maya wiki
  3. 3dMax wiki
  • 這些工具能只能做遊戲、APP或AR/VR嗎?
  • 擔心學了以後無處可用嗎?
  • 這幾週的課程內容會教大家,我們是怎麼把工具當作工具用

例用工具解決問題

  1. 發現問題
  2. 假設解決辦法
  3. 使用工具製作出解決辦法
  4. 使用解決辦法來解決問題

例:RobotSim Webplayer

探索新世界-RobotSim

想看看在Unity內可以怎麼玩機器手臂嗎?
Unity還有這種使用方式(之二)?! 只有想不到,沒有做不到。

想像力是你的超能力

在RobotSim 中還能做什麼?

加入夾爪Gripper 功能

  1. 夾爪程式
  2. 手臂指令程式
  3. Test 測試夾爪功能
  4. 夾爪建構/動畫 Animator
    • 建立夾爪(建模軟體或在Unity內可用ProBuilder)
    • 建立動畫(動畫軟體或在Unity內製作Animator動畫)
    • 於Tool上加入Animator用來播放夾爪動畫(Idle、Lock、UnLock)
  5. Demo

    客人這是你的章魚燒。給你~不給你~再給你~才怪~啦啦啦~
    Image

//Gripper.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gripper : MonoBehaviour
{
	// Gripper程式會有2種模擬夾取
	// 1.利用OnTriggerEnter自動取得在夾取範圍內的物件,夾取指令時將該物件的parent設為Gripper
	// 2.以夾爪播放夾取動畫的方式移動夾爪,並利用Rigidbody產生夾取

	//準備夾取的物件
	public Transform readyGet;
	//目前夾持的物件
	public Transform holdingObject;

	//夾取指令(將readyGet物件Parent設為Gripper)
	public void Lock(Transform product)
	{
		if (holdingObject == null)
		{
			if (product)
			{
				product.transform.parent = transform;
				holdingObject = product;
			}
		}
	}

	//傳回目前所夾持物
	public Transform Unlock()
	{
		Transform returnObject = holdingObject;
		holdingObject = null;//清空目前所持物

		return returnObject;
	}

	//夾取readyGet物件
	public void LockReadyGet()
	{
		Lock(readyGet);
	}
	//放開夾取物件
	public void UnlockToWorld()
	{
		if (holdingObject)
		{
			holdingObject.parent = null;
		}
		holdingObject = null;//把手上拿著的東西丟到世界Root去
	}
	//偵測目前可夾取物
	void OnTriggerEnter(Collider other)
	{
		readyGet = other.transform;
	}
	//移除目前圖夾取物
	void OnTriggerExit(Collider other)
	{
		if (readyGet == other.transform)
		{
			readyGet = null;
		}
	}
}

//RobotCommandGripper.cs
using UnityEngine;
using RobotSim;
using System;

public class RobotCommandGripper : RobotCommand
{
	//對應操作的夾爪
	public Gripper gripper;
	//夾爪動畫
	public Animator animatorGripper;
	//夾持命令
	public bool Lock = false;

	//檢查是否有設定好夾爪
	public override bool Check()
	{
		if (gripper)
		{
			return true;
		}
		else
		{
			errorMassage = "Gripper is NULL";
			return false;
		}
	}

	//執行夾爪動作
	public override int Execute()
	{
		if (Lock)
		{
			//夾取(以設定Parent方式)
			gripper.LockReadyGet();
			//夾取(播放動畫)
			if (animatorGripper)
			{
				animatorGripper.speed = 1;
				animatorGripper.Play("Lock", -1, 0);
			}
		}
		else
		{
			//放開(以設定parent方式)
			gripper.UnlockToWorld();
			//放開(播放動畫)
			if (animatorGripper)
			{
				animatorGripper.speed = 1;
				animatorGripper.Play("UnLock", -1, 0);
			}
		}
		//動作完成,執行下一行
		return (line + 1);
	}

	public override string ExportDat()
	{
		//不需要輸出任何程式到Dat檔
		return "";
	}

	public override string ExportSrc()
	{
		//輸出  GripperLock(true/false);  至 手臂程式src檔內
		return tab + "GripperLock(" + Lock.ToString() + ");" + Environment.NewLine;
	}

	public override string UpdateName()
	{
		//更新Gameobject在階層視窗內的名稱
		return (gameObject.name = "GripperLock(" + Lock.ToString() + ")");
	}

}

模擬手臂指令 RobotCommand 流程講解

夾娃娃機控制 RobotCommandControlRobot

  1. UI控制
  2. 更新手臂動作
  3. (修改)夾爪控制
  4. Demo

    簡單的試夾一下~ Image

//RobotCommandControlRobot.cs
using UnityEngine;
using UnityEngine.UI;
using RobotSim;

public class RobotCommandControlRobot : RobotCommand
{
	public RobotPoint moveTarget; //等待點
	public RobotPoint gripTarget; //夾取點
	public Button ButtonForward;  //UI向前按鈕
	public Button ButtonBack;     //UI向後按鈕
	public Button ButtonLeft;     //UI向左按鈕
	public Button ButtonRight;    //UI向右按鈕
	public Button ButtonOK;       //UI夾取按鈕

	private float moveX = 0;  //按下左或右時移動的距離
	private float moveZ = 0;  //按下前或後時前後移動的距離
	private bool done = false;  //是否已移動完畢(手臂可以繼續動作向下夾取)
	
	public override bool Check()
	{
		if (moveTarget == null)
		{
			errorMassage = "未設定等待點";
			return false;
		}
		if (gripTarget == null)
		{
			errorMassage = "未設定夾取點";
			return false;
		}	
		return true;
	}

	//在Unity環境中每FixedUpdate會呼叫此Execute()一次
	public override int Execute()
	{
		Vector3 updatePosition = moveTarget.transform.position;
		//原本的預備點

		updatePosition.x += moveX;//更新左右位置
		updatePosition.z += moveZ;//更新前後位置
		moveX = 0;
		moveZ = 0;
		
		moveTarget.transform.position = updatePosition;
		//將變更套用至預備點

		updatePosition.y = gripTarget.transform.position.y;
		//更新夾取點的高度值
		
		gripTarget.transform.position = updatePosition;
		//將變更套用至夾取點

		robot.Inverse(moveTarget.transform);
		//手臂動作更新

		//若操作已完成,則讓手臂程式執行下一行程式,否則繼續執行目前這行程式
		if (done)
		{
			done = false;
			return (line + 1);
		}
		else
		{
			return line;
		}
	}
	
	//當選擇匯出程式時會執行此ExportDat(),將回傳的值寫進手臂程式原始src檔中
	public override string ExportDat()
	{
		return "";
	}

	//當選擇匯出程式時會執行此ExportSrc(),將回傳的值寫進手臂程式原始dat檔中
	public override string ExportSrc()
	{
		return "";
	}

	//更新在階層列表上的此物件名稱
	public override string UpdateName()
	{
		return (gameObject.name = "Move(" + moveTarget.name + "," + gripTarget.name + ")");
	}

	//初始化 設定UI按鈕按下時移動數值變更
	void Start()
	{
		ButtonForward.onClick.AddListener(
			delegate
			{
				moveZ = 0.01f;//向前移動1公分
			});
		ButtonBack.onClick.AddListener(
			delegate
			{
				moveZ = -0.01f;//向後移動1公分
			});
		ButtonLeft.onClick.AddListener(
			delegate
			{
				moveX = -0.01f;//向左移動1公分
			});
		ButtonRight.onClick.AddListener(
			delegate
			{
				moveX = 0.01f;//向右移動1公分
			});

		ButtonOK.onClick.AddListener(
			delegate
			{
				done = true;//動作完成,開始夾
			});
	}
	
}
//Gripper.cs
	//放開夾取物件
	public void UnlockToWorld()
	{
		if (holdingObject)
		{
			holdingObject.parent = null;
			//若物件上有剛體則開啟重力(讓物體隨重力掉落)
			if (holdingObject.GetComponent<Rigidbody>())
			{
				holdingObject.GetComponent<Rigidbody>().useGravity = true;
			}
		}
		holdingObject = null;//把手上拿著的東西丟到世界Root去
	}

使用物理方式夾取物件 Collider & Rigidbody

  1. 建模 Cube夾爪
  2. 動畫 Animator
    • 必需要有Idle、Lock、UnLock 三組動畫
    • Idle 當夾爪預設無動作時
    • Lock 夾爪夾取動作
    • UnLoad 夾爪放開動作
  3. 修改被夾取的物件
    • Collider IsTrigger 為 False
    • Rigidbody use Gravity
  4. DEMO 抓抓 enter image description here