AndroidのContraintLayoutとiOSのAutoLayout

 AndroidアプリとiOSアプリを開発する際に、異なる解像度を対応するために、制約を使うことが多い。その際に、よく利用される機能として、AndroidのContraintLayoutとiOSのAutoLayoutという機能である。

iOS:
iOSにおいて、ptという解像度単位を利用している。そして、異なる解像度に対して、AutoLayoutを利用している。
qiita.com
dev.classmethod.jp


Android:
Androidにおいて、dpの解像度単位を利用している。2016年が導入されたConstraintLayout機能を利用することで、ほぼiOSのAutoLayoutと同じようなアプローチで異なる解像度を対応できるようになった。
blog.techium.jp

Unity UFrame MVVMを使ってみる

 バージョン1.63r1をインポートしたが、エラー二つあった。
次のような修正によって解決:

1.MainThreadDispatcher.cs
274行と258行以下のように修正

distpacher2.StartCoroutine(routine.ToString());

return dispatcher.StartCoroutine(routine.ToString());

2.UGUIBindings.cs
1行以下のように修正

#if UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2||UNITY_5_6

3Dキャラクターのコントロール方法(追記1)

bankzhy.hatenablog.com
前回の記事で、回転情報がモデルに含まれてい
ない素材に対する制御方法を実装しました。しかし、前回の実装方法のままだと、2.5Dゲームに十分対応できるが、3Dゲームのように動くことができない。3Dゲームのキャラクターのコントロール方法以下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour {
public float RunSpeed = 100.0f;
public float TurnSmoothTime = 0.2f;

private Rigidbody m_Rigidbody;
private Animator m_Anim;
private float m_TurnSmoothVelocity;
private Vector3 m_CurrentRotation;//現在キャラクターの方向を記録する変数
// Use this for initialization
void Start () {
m_Rigidbody = GetComponent<Rigidbody>();
m_Anim = GetComponent<Animator>();
Debug.Log(Vector3.up);
m_CurrentRotation = transform.eulerAngles;
}

// Update is called once per frame
void Update()
{
float inputX = 0f;
float inputZ = 0f;

inputX = CrossPlatformInputManager.GetAxis("Horizontal");
inputZ = CrossPlatformInputManager.GetAxis("Vertical");

Vector2 inputDir = new Vector2(inputX,inputZ).normalized;
if (inputDir != Vector2.zero)
{
//z方向とx方向のtanを求め、その角度をrotationに代入する。
//Mathf.Rad2Degはradianから度に変換する。これは ” 360/(PI * 2) " に等しいです。
float rotation = Mathf.Atan2(inputDir.x, inputDir.y) * Mathf.Rad2Deg;
//現在キャラクターの方向に対する方向へ変換
float targetrotation = m_CurrentRotation.y + rotation;
//キャラクターのRotationを指定する。
transform.localEulerAngles =Vector3.up* Mathf.SmoothDampAngle(transform.eulerAngles.y, targetrotation, ref m_TurnSmoothVelocity,TurnSmoothTime);
}
else
{
UpdateCurrentRotation();
}

// m_Rigidbody.velocity=new Vector3(inputX, 0, inputZ)*RunSpeed*Time.deltaTime;
//入力の方向を現在キャラクターの方向に対する方向へ変換
Vector3 velocityDirection = Quaternion.Euler(0, m_CurrentRotation.y, 0) * new Vector3(inputX, 0, inputZ);
m_Rigidbody.velocity = velocityDirection * RunSpeed * Time.deltaTime;
m_Anim.SetFloat("inputX", inputX);
m_Anim.SetFloat("inputZ", inputZ);

}
//キャラクターの方向を更新する
public void UpdateCurrentRotation()
{
m_CurrentRotation = transform.eulerAngles;
}
}

タッチしたポイントにジョイスティックが現れる実装方法

 最近のスマホ3Dゲームによくあるタッチしたポイントにジョイスティックが現れる実装方法について、
kan-kikuchi.hatenablog.com
こちらのサイトで実装方法を紹介した。
 しかし、もっと簡単な方法がないかを考えてみった。以下に、自分の実装方法を紹介する。
 

1.まず、UnityのStanddardAssetをインポートし、MobileSingleStickControlをSceneに配置する。
2.MobileSingleStickControlを親とし、Panelを一つ作成する。子GameObjectの一番上に配置、サイズ約画面サイズの半分。Joystickのbaseがあれば、JoyStickの親オブジェクトを作成する。
3.以下のScriptを作成し、Panelにアタッチし、InspectorのJoystickのGameObjectに2のJoystickをドラッグするだけ!!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityStandardAssets.CrossPlatformInput;
public class JoyStickInvisiable : MonoBehaviour,IPointerDownHandler,IPointerUpHandler,IDragHandler {
    public GameObject JoyStick;
    private Vector3 m_StartPos;
    private Vector3 m_CurrentPos;
    public void OnDrag(PointerEventData eventData)
    {
        JoyStick.GetComponentInChildren<Joystick>().OnDrag(eventData);
    }

    public void OnPointerDown(PointerEventData eventData)
    {

        m_CurrentPos = Input.mousePosition;
        JoyStick.transform.position = m_CurrentPos;
        JoyStick.GetComponentInChildren<Joystick>().m_StartPos = m_CurrentPos;
        JoyStick.GetComponentInChildren<Joystick>().OnPointerDown(eventData);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        JoyStick.transform.position = m_StartPos;
        JoyStick.GetComponentInChildren<Joystick>().m_StartPos = m_StartPos;
        JoyStick.GetComponentInChildren<Joystick>().OnPointerUp(eventData);
        
    }

    // Use this for initialization
    void Awake () {
        m_StartPos = JoyStick.transform.position;
	}
	
}

3Dキャラクターのコントロール方法について

 Unity において、使用する3DモデルのAnimationの違いにより、キャラクターをコントロールする実装方法が変わる。

1.モデルのAnimationの中にRotation情報が含まれている場合
コードにおいて、Rotationに関する制御必要がない。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class UNITYCHANController : MonoBehaviour {
public float MovePower=20f;
public float TurnPower=50f;

private Animator anim;
private float inputH;
private float inputV;
private Rigidbody m_Rigidbody;
// Use this for initialization
void Start () {
anim = GetComponent<Animator>();
m_Rigidbody = GetComponent<Rigidbody>();
}

// Update is called once per frame
void Update () {

inputH = Input.GetAxis("Horizontal");
inputV = Input.GetAxis("Vertical");

anim.SetFloat("inputH", inputH);
anim.SetFloat("inputV", inputV);

float moveZ = inputV * MovePower * Time.deltaTime;
float moveX = inputH * TurnPower * Time.deltaTime;
m_Rigidbody.velocity = new Vector3(moveX, 0, moveZ);
Debug.Log(m_Rigidbody.velocity);

if (Input.GetKeyDown(KeyCode.LeftShift))
{
anim.SetBool("run", true);
MovePower *= 2f;
}else if (Input.GetKeyUp(KeyCode.LeftShift))
{
anim.SetBool("run", false);
}

if (Input.GetKeyDown(KeyCode.Space))
{
anim.SetBool("jump", true);
}else if (Input.GetKeyUp(KeyCode.Space))
{
anim.SetBool("jump", false);
}
}
}

2.モデルのAnimationの中にRotation情報が含まれていない場合、
コードでキャラクターのRotation情報を変える必要がある。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour {
    public float RunSpeed = 100.0f;
    public float TurnSmoothTime = 0.2f;

    private Rigidbody m_Rigidbody;
    private Animator m_Anim;
    private float m_TurnSmoothVelocity;
  // Use this for initialization
  void Start () {
        m_Rigidbody = GetComponent<Rigidbody>();
        m_Anim = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        float inputX = 0f;
        float inputZ = 0f;

        inputX = Input.GetAxis("Horizontal");
        inputZ = Input.GetAxis("Vertical");

        Vector2 inputDir = new Vector2(inputX,inputZ).normalized;
        if (inputDir != Vector2.zero)
        {
            //z方向とx方向のtanを求め、その角度をrotationに代入する。
            //Mathf.Rad2Degはradianから度に変換する。これは ” 360/(PI * 2) " に等しいです。
            float rotation = Mathf.Atan2(inputDir.x, inputDir.y) * Mathf.Rad2Deg;
            //キャラクターのRotationを指定する。
            transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, rotation, ref m_TurnSmoothVelocity,TurnSmoothTime);
        }

        m_Rigidbody.velocity=new Vector3(inputX, 0, inputZ)*RunSpeed*Time.deltaTime;
        m_Anim.SetFloat("inputX", inputX);
        m_Anim.SetFloat("inputZ", inputZ);

    }

txtファイルの処理(データ更新、修正)JAVA,Python

①旧社員マスタ(olddata.txt)

1010 山本孝太郎      00128000
1011 田所勉          00158900
1020 山本貴宏        00235800
1021 吉田博美        00189000
1022 白石昌弘        00178900
1024 菊地英明        00167800
1025 坂本栄一        00189000
  ②基本給変更データ(changedata.txt)

1010 00138000
1012 00162000
1020 00245800
1021 00195000
1023 00186000
1024 00179800

Java

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> number=new ArrayList<>();
        ArrayList<String> name=new ArrayList<>();
        ArrayList<String> payment=new ArrayList<>();
        HashMap<String,String> newpayment=new HashMap<>();
        HashMap<String, String> numname=new HashMap<String, String>();
        HashMap<String, String> numpayment=new HashMap<String, String>();
        ArrayList<String> newnumber=new ArrayList<>();
        try{
            File oldfile=new File("E://programtrain//olddata.txt");
            BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(oldfile),"Unicode"));
            String line;

            while((line=reader.readLine())!=null){
                String words[]=line.split("[\\s]+");//空白が何個でも分ける
                number.add(words[0]);
                name.add(words[1]);
                payment.add(words[2]);
                numname.put(words[0], words[1]);
                numpayment.put(words[0], words[2]);
            }
            
            
        }catch(FileNotFoundException e){
            System.out.println(e);
        }catch(IOException e){
            System.out.println(e);
        }
        
        try{
            File newfile=new File("E://programtrain//changedata.txt");
            BufferedReader newreader=new BufferedReader(new InputStreamReader(new FileInputStream(newfile),"Unicode"));
            String line;
            while((line=newreader.readLine())!=null){
                String words[]=line.split("[\\s]+");
                newpayment.put(words[0], words[1]);
                    newnumber.add(words[0]);
                
                
            }
            
        }catch(FileNotFoundException e){
            System.out.println(e);
        }catch(IOException e){
            System.out.println(e);
        }
        
        System.out.println("        社員マスタ更新");
        System.out.println("番号"+" "+"氏名"+"        "+"旧基本給"+" "+"新基本給");
        int numberlength=number.size();
        
        for(int i=0;i<number.size();i++){
            if(newnumber.contains(number.get(i))==false){
                newnumber.add(number.get(i));
            }
        }
        Collections.sort(newnumber);

            
        for(int i=0;i<newnumber.size();i++){
            if(numname.containsKey(newnumber.get(i))){
                if(newpayment.containsKey(newnumber.get(i))){
                    System.out.println(newnumber.get(i)+" "+numname.get(newnumber.get(i))+" "+numpayment.get(newnumber.get(i))+" "+newpayment.get(newnumber.get(i))+" "+"更新");
                }else{
                    System.out.println(newnumber.get(i)+" "+numname.get(newnumber.get(i))+" "+numpayment.get(newnumber.get(i))+" "+numpayment.get(newnumber.get(i)));
                }
            }else{
                System.out.println(newnumber.get(i)+" "+numname.get(newnumber.get(i))+" "+numpayment.get(newnumber.get(i))+" "+newpayment.get(newnumber.get(i))+" "+"更新");
            }
        }

    }
    
    public static void loadFile(String filename){
        
    }
    

}

Python

from  texttable import Texttable
numName={}
numPay={}
newnumPay={}
newnumName={}
f=open("olddata.txt","r",encoding="utf-8-sig")
lines=f.readlines()
for line in lines:
    wordlist=line.split(" ")
    newwordlist=[]
    for word in wordlist:
        if(word!=""):
            newwordlist.append(word.strip())
    numName.update({newwordlist[0]:newwordlist[1]})
    numPay.update({newwordlist[0]:newwordlist[2]})
cf=open("changedata.txt","r",encoding="utf-8-sig")
clines=cf.readlines()
for line in clines:
    wordlist=line.split(" ")
    newnumPay.update({wordlist[0].strip():wordlist[1].strip()})
numPay.update(newnumPay)
snumPay=sorted(numPay.items())
table=Texttable()
header=['番号','氏名','旧基本給','新基本給']
table.header(header)
for tp in snumPay:
    if tp[0] in numName:
        table.add_row([tp[0],numName[tp[0]],numPay[tp[0]],tp[1]])
    else:
        table.add_row([tp[0],"NULL","NULL",tp[1]])
print(table.draw())
cf.close()

プロジェクトマネジメント(トラッキングとコントロール)

ITプロジェクトのトラッキングとコントロール

 プロジェクトの状況と実績を的確かつ継続的に把握し、計画からの乖離や逸脱に対して適切な対策を講じるための管理プロセスである。

  • 品質のトラッキング
    1. 品質マネジメント:当該プロジェクトが所期の要求を満足していることを保証するために必要な一連の業務プロセス
      1. 品質計画
      2. 品質保証
  • 品質管理
  1. システムの品質
    1. 機能性
    2. 信頼性
  • 使用性
  1. 効率性
  2. 保守性
  3. 移植性
  1. 品質管理計画
    1. 品質管理の目的と方法
    2. スケジュール
  • 品質管理の組織、体制
  1. ウォークスルー、インスペクションの方法
  1. 問題管理
    1. 問題管理の機能
      1. 問題報告書
      2. 変更管理
      3. 問題解決の評価
      4. 再発防止
    2. 問題管理のツールと技法
      1. パレート図
      2. 特性要因図(フィッシュボーン、石川図)
    3. 変更管理
  • 進捗のトラッキング
  • コストのトラッキング
  • リスクのトラッキング
  • 計画とのギャップの要因分析
  • 対策の立案と実施
  • レポーティング
  • ウォークスルー
    1. 机上シミュレーション
    2. 少人数、短時間で効率的な運営
    3. 開発者自身が参加メンバーの選定も含めて、自主的に招集
  • ウォークスルーの目的
    1. 欠陥の早期発見と除去
    2. 設計段階、作成段階での品質の作りこみ
  • ウォークスルーの対象物
    1. DFD、データ正規化結果、ER図、データ、ディクショナリ
    2. 外部入出力仕様、DB仕様、処理機能記述、モジュール構造
    3. 各種作業手順書
    4. プロトタイプ
  • ウォークスルーの実施時期
    1. 作業の立ち上がり時点をはじめとして、作業段階で適宜実施
    2. 作成者自身による点検終了後、または、作業が壁にぶつかったときなど、数日以内に実施
  • EVM
    1. SV=EV-PV=-100 CV=EV-AC=-160
    2. SPI=EV/PV CPI=EV/AC

予測コスト=元総コスト/CPI 予測期間=元総期間/SPI